【剑指offer】1-14题

来源:互联网 发布:能查汽档案的软件 编辑:程序博客网 时间:2024/05/16 06:56


1.二维数组中的查找

  在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

 算法思想:从矩阵的最右上角开始,如果该整数小于右上角这个数,则去掉该列;如果该整数大于右上角这个数,则去掉该行。

class Solution {public:    bool Find(int target, vector<vector<int> > array) {        if(array.empty()) return false;        int rows=array.size();        int columns=array[0].size();        //bool found=false;                 int x=0,y=columns-1;        while(x>=0 && x<rows && y>=0 && y<columns)        {            if(array[x][y]==target)            {                return true;            }                         if(array[x][y]>target) y--;            if(array[x][y]<target) x++;        }        return false;    }};

2.替换空格

  请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

  算法思想:两个指针,一个指向原字符串的末尾为p1,一个指向替换后的字符串的末尾为p2,两者同时向前移动。p1遇到非空格就复制到p2的位置,遇到空格就将%20复制到p2的位置,并继续向前移动两个指针。当p1到头或者p1和p2相等时,停止移动。

  

class Solution {public:    void replaceSpace(char *str,int length) {                 if(str==NULL || length<=0)        {                   return;        }                 int numberOfBlank=0;        int oldLength=0;          //int newLength=0;        int i=0;                   while(str[i]!='\0')          {                oldLength++;              if(str[i]==' ')              {                 numberOfBlank++;                 }              i++;           }                 int newLength=numberOfBlank*2+oldLength;        if(newLength>length)        {            return;        }                          int oldIndex=oldLength;        int newIndex=newLength;                 while(oldIndex>=0 && newIndex>oldIndex)        {            if(str[oldIndex]==' ')            {                str[newIndex--]='0';                str[newIndex--]='2';                str[newIndex--]='%';            }            else            {                str[newIndex--]=str[oldIndex];            }            oldIndex--;        }     }};

3.从尾到头打印链表

输入一个链表,从尾到头打印链表每个节点的值。

算法思想:用一个栈。

/***  struct ListNode {*        int val;*        struct ListNode *next;*        ListNode(int x) :*              val(x), next(NULL) {*        }*  };*/class Solution {public:    vector<int> printListFromTailToHead(ListNode* head) {                 vector<int> list;        stack<int> list_stack;                 ListNode *p=head;                 while(p!=NULL)        {           list_stack.push(p->val);           p=p->next;        }                 while(!list_stack.empty())         {            list.push_back(list_stack.top());            list_stack.pop();        }                 return list;    }};

4.重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

算法思想:递归,确定根节点后,不断找子树中的根节点。

/** * Definition for binary tree * struct TreeNode { *     int val; *     TreeNode *left; *     TreeNode *right; *     TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */class Solution {public:    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {                int len=vin.size();//节点的个数        int root=0;                 if(len==0)        {            return NULL;        }                 vector<int> frontPre,frontVin,backPre,backVin;        TreeNode *head=new TreeNode(pre[0]); //定义根节点                 for(int i=0;i<len;i++)        {            if(pre[0]==vin[i])            {                root=i;                break;            }        }                 //将根节点左侧节点存储到新序列中        for(int i=0;i<root;i++)        {            frontPre.push_back(pre[i+1]);            frontVin.push_back(vin[i]);        }                 //将根节点右侧节点存储到新序列中        for(int i=root+1;i<len;i++)        {            backPre.push_back(pre[i]);            backVin.push_back(vin[i]);        }                 head->left=reConstructBinaryTree(frontPre,frontVin);        head->right=reConstructBinaryTree(backPre,backVin);                 return head;    }};

5.用两个栈实现队列

用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

算法思想:push直接压住一个栈;pop先压入第一个栈,当第二个栈为空的时候压入第二个栈,之后弹出,第二个栈不为空的时候先弹出再压入。

class Solution{public:    void push(int node) {        stack1.push(node);    }     int pop() {                while(stack2.empty())       {             while(!stack1.empty())           {              stack2.push(stack1.top());              stack1.pop();           }       }                     int tmp=stack2.top();       stack2.pop();                   return tmp;            } private:    stack<int> stack1;    stack<int> stack2;};


6.旋转数组的最小数字

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

算法思想:直接用sort函数排序。

class Solution {public:    int minNumberInRotateArray(vector<int> rotateArray) {                 sort(rotateArray.begin(),rotateArray.end());                          return rotateArray[0];    }};


7.斐波那契数列

大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。

n<=39

算法思想:就普通计算。

class Solution {public:    int Fibonacci(int n) {                 int F[40];        F[0]=0;        F[1]=1;                 for(int i=2;i<=n;i++)        {            F[i]=F[i-1]+F[i-2];        }                 return F[n];     }};


8.跳台阶

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

算法思想:在n阶台阶时,两种情况,一种是剩下一个台阶则有f(n-1)种方法,另外一种是剩下两个台阶一步跨上去有f(n-2)种方法,所以f(n)=f(n-1)+f(n-2)。

class Solution {public:    int jumpFloor(int number) {                 if(number==1)        {            return 1;        }        else if(number==2)        {            return 2;        }        else        {           int result;           int a=jumpFloor(number-1);           int b=jumpFloor(number-2);                        result=a+b;                        return result;        }             }};

9.变态跳台阶

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

算法思想:n阶台阶时,还剩0阶台阶则有一种方法f(0),还剩1阶台阶则有f(n-1)方法,还剩2阶台阶则有f(n-2)方法,...,还剩n-1阶台阶择优f(1)方法。综上f(n)=f(0)+f(1)+..f(n-1)。

class Solution {public:    int jumpFloorII(int number) {                 if(number==0||number==1)        {            return 1;        }               else if(number==2)        {            return 2;        }               else        {            int sum=0;            for(int i=0;i<number;i++)            {                sum+=jumpFloorII(i);            }                         return sum;        }          }};

10.矩形覆盖

我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

算法思想:还剩一个2*1则有f(n-1)种方法,还剩2*2则有f(n-2)种方法,所以f(n)=f(n-1)+f(n-2)。

class Solution {public:    int rectCover(int number) {                 if(number==0)        {           return 0;        }                 if(number==1)        {            return 1;        }                   if(number==2)        {            return 2;        }        return rectCover(number-1)+rectCover(number-2);               }};

11.二进制中1的个数

输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

算法思想:假设一个二进数为1100,减去1后变为1011,相与之后变为1000,再减去1变为0111,再与1000相与变为0000,两个1.

class Solution {public:     int  NumberOf1(int n) {                   int count=0;                   while(n!=0)         {             n=n&(n-1);             count++;         }                   return count;     }};


12.数值的整数次方

给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。

算法思想:正常计算就好。

class Solution {public:    double Power(double base, int exponent) {                 double sum=1;                 if(exponent==0)        {            return 1;        }        else        {           for(int i=0;i<abs(exponent);i++)           {               sum*=base;           }                        return exponent>0?sum:1/sum;        }         }};


13.调整数组顺序使奇数位于偶数前面

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

算法思想:创建一个新数组,先把奇数存入,再把偶数存入,然后赋值给整数数组。【空间复杂度好像高?】

class Solution {public:    void reOrderArray(vector<int> &array) {                 int len=array.size();        vector<int> temp;                 for(int i=0;i<len;i++)        {           if(array[i]%2!=0)           {              temp.push_back(array[i]);           }        }                 for(int i=0;i<len;i++)        {            if(array[i]%2==0)            {               temp.push_back(array[i]);            }        }                 array=temp;               }};

14.链表中倒数第k个节点

输入一个链表,输出该链表中倒数第k个结点。

算法思想:两个指针分别为p1和p2,p2先移动k个节点,之后p1和p2同时移动,当p2到达链表尾部时,p1所在位置即为倒数第k个节点。

/*struct ListNode {    int val;    struct ListNode *next;    ListNode(int x) :            val(x), next(NULL) {    }};*/class Solution {public:    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {                 ListNode *p1=pListHead;        ListNode *p2=pListHead;                 for(int i=0;i<k;i++)        {              if(p2==NULL)            {                return NULL;            }            p2=p2->next;        }                 while(p2)        {            p2=p2->next;            p1=p1->next;        }                return p1;      }};







0 0
原创粉丝点击