剑指offer第二章

剑指offer第二章

1.二维数组中的查找

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

 1 class Solution {
 2 public:
 3     bool Find(int target, vector<vector<int> > array) 
 4     {
 5         /*二维数组的行数和列数*/
 6          int rows = array.size();
 7          int columns = array[0].size();
 8         
 9             int row;
10             int column;
11         for (row = rows - 1, column = 0; row >= 0 && column<columns;)
12         {
13              if (target == array[row][column])
14                  return true;
15             if (target<array[row][column])
16              {
17                  row--;
18                  continue;
19              }
20              if (target>array[row][column])
21              {
22                  column++;
23                  continue;
24              }
25          }
26          return false;
27     }
28 };

2.替换空格

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

 1 class Solution {
 2 public:
 3     void replaceSpace(char *str,int length) 
 4     {
 5         if(str==NULL||length<0)
 6         {
 7             return;
 8         }
 9         int originalLength=0;
10         int numberOfBlank=0;
11         int i=0;
12         while(str[i]!='')//计算原始字符串长度和空格数目
13         {
14             ++originalLength;
15             if(str[i]==' ')
16             {
17                 ++numberOfBlank;
18             }
19             ++i;
20         }
21         int newLength=originalLength+numberOfBlank*2;//替换之后新的长度
22         if(newLength>length)
23             //溢出、越界
24             return;
25         int indexOfOriginal=originalLength;
26         int indexOfNew=newLength;
27         while(indexOfOriginal>=0&&indexOfNew>indexOfOriginal)
28         {
29             if(str[indexOfOriginal]==' ')//找到空格,依次插入‘0’‘2’‘%’
30             {
31                 str[indexOfNew--]='0';
32                 str[indexOfNew--]='2';
33                 str[indexOfNew--]='%';
34             }
35             else
36             {
37                 str[indexOfNew--]=str[indexOfOriginal];
38             }
39             --indexOfOriginal;
40         }
41     }
42 };

3.从尾到头打印链表

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

 1 //struct ListNode {
 2 //int val;
 3 //struct ListNode *next;
 4 //ListNode(int x) :
 5 //val(x), next(NULL) {
 6 //}
 7 //};
 8 
 9 class Solution{
10 public:
11     vector<int> printListFromTailToHead(struct ListNode* head){
12         vector<int> result;
13         struct ListNode* pNode=head;
14         while(pNode!=NULL){
15             result.push_back(pNode->val);
16             pNode=pNode->next;
17         }
18         reverse(result.begin(),result.end());//applying reverse()
19         return result;
20     }
21 };

4.重建二叉树

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

 1 /**
 2  * Definition for binary tree
 3  * struct TreeNode {
 4  *     int val;
 5  *     TreeNode *left;
 6  *     TreeNode *right;
 7  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 8  * };
 9  */
10 class Solution {
11 public:
12     struct TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> in) 
13     {
14         //判定递归终止条件;
15         if(pre.size() == 0 || in.size() == 0) 
16         {
17             return NULL;
18         }
19         //定义Node节点并其求根节点;
20         int root = pre[0];
21         TreeNode* node = new TreeNode(root);
22         vector<int>::iterator it;
23         //1.求左右子树的遍历序列;
24         vector<int> preLeft, preRight, inLeft, inRight;
25         //(1).求根节点在中序遍历序列中的位置;
26         vector<int>::iterator i;
27         for(it = in.begin(); it != in.end(); it++)
28         {
29             if(root == *it)
30             {
31                 i = it;
32             }
33         }
34         //(2).求左右子树的中序遍历子序列;
35         int k = 0;
36         for(it = in.begin(); it != in.end(); it++) 
37         {
38             if(k == 0)
39             {
40                 inLeft.push_back(*it);
41             }
42             else if(k == 1) 
43             {
44                 inRight.push_back(*it);
45             }
46             else {}
47             if(it == i) 
48             {
49                 k = 1;
50             }  
51         }
52         //(3).求左右子树的前序遍历子序列;
53         k = 0;
54         vector<int>::iterator ite;
55         for(it = pre.begin()+1; it != pre.end(); it++) 
56         {
57             for(ite = inLeft.begin(); ite != inLeft.end(); ite++) 
58             {
59                 if(*it == *ite) 
60                 {
61                     preLeft.push_back(*it);
62                     k = 1;
63                 }
64             }
65             if(k == 0)
66             {
67                 preRight.push_back(*it);
68             }
69             k = 0;
70         }
71         //根据遍历序列求出跟的左右节点;
72         node->left = reConstructBinaryTree(preLeft,inLeft);
73         node->right = reConstructBinaryTree(preRight,inRight);
74         //返回节点地址;
75         return node; 
76     }
77 };

5.用两个栈实现队列

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

<分析>: 
入队:将元素进栈A 
出队:判断栈B是否为空,如果为空,则将栈A中所有元素pop,并push进栈B,栈B出栈; 
 如果不为空,栈B直接出栈。
 1 class Solution
 2 {
 3 public:
 4     void push(int node) 
 5     {
 6         stack1.push(node);       
 7     }
 8     int pop() 
 9     {
10         int a;
11         if(stack2.empty())
12         {
13             while(!stack1.empty())
14             {
15                 a=stack1.top();
16                 stack2.push(a);
17                 stack1.pop();
18             }
19         }
20         a=stack2.top();
21         stack2.pop();
22         return a;
23     }
24 private:
25     stack<int> stack1;
26     stack<int> stack2;
27 };

6.旋转数组的最小数字

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
 1 class Solution {
 2 public:
 3      int minNumberInRotateArray(vector<int> rotateArray)
 4      {
 5         //数组为空时
 6         if(rotateArray.size() == 0)
 7             return -1;
 8         //前部分数据旋转
 9         for(int i = 0; i < rotateArray.size() - 1; i++)
10         {
11             if (rotateArray[i] > rotateArray[i + 1])
12                 return rotateArray[i + 1];
13         }
14         //全部数据旋转,相当于没有旋转,最小数即为第一个数
15         return rotateArray[0];
16      }
17 };

7.菲波那切数列

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

 1 class Solution {
 2 public:
 3     int Fibonacci(int n)
 4     {
 5         int result[2]={0,1};
 6         if(n<2)
 7             return result[n];
 8         long long f1=1;
 9         long long f2=0;
10         long long fn=0;
11         for(int i=2;i<=n;i++)
12         {
13             fn=f1+f2;
14             f2=f1;
15             f1=fn;
16         }
17         return fn;
18     }
19 };

8.二进制中”1“的个数

输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
解法1:首先把n和1做与运算,判断n的最低位是不是为1
            接着把1左移一位得到2,在与n做与运算,就能判断n的次低位是不是1
            ......这样反复左移,每次都能判断n的其中一位是不是1。
            循环的次数等于整数二进制的位数
解法2:首先把一个整数减去1,再和原整数做与运算,会把最右边一个1变成0.
            那么一个整数的二进制表示中有多少个1,就可以进行多少次这样的操作
            循环的次数等于整数中1的个数
 1 class Solution {
 2 public:
 3      int  NumberOf1(int n)
 4      {
 5          int count=0;//统计的值初始化
 6          unsigned int flag=1;//设置一个标志,作为循环结束的终止条件
 7          while(flag)
 8          {
 9              //首先把n和1做与运算,判断n的最低位是不是为1
10             //接着把1左移一位得到2,在与n做与运算,就能判断n的次低位是不是1
11             //......这样反复左移,每次都能判断n的其中一位是不是1。
12            // 循环的次数等于整数二进制的位数
13              if(n&flag)
14                  count++;
15              flag=flag<<1;
16          }
17          return count;
18      }
19 };
原文地址:https://www.cnblogs.com/lxt1105/p/7411676.html