剑指offer二刷
1.二维数组的查找
从上到下递增,从左到右递增,数组的每个L型序列都是个递增序列。
思路(1):从左下角开始判断,如果大于目标,则在上方;小于目标,则在下方。
思路(2):对每一个一维数组用二分查找。
2.替换空格
把给定字符串所有的空格换成%20。
如果从前往后替换的话,每替换一次,后面所有的字符都要整体后移,复杂度非常高。应该从后往前替换,先找出空格数目count,第一个空格后面的字符后移count*2,conut--,以此类推。
3.重建二叉树
已知先序遍历和中序遍历,重建二叉树。
根据先序遍历第一个元素为根,把中序遍历分成左右两个字树,同时先序遍历除了第一个元素外,也分成两个子树。然后子树在同上,递归运算,直到子树为空,返回。
/**
* 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 = pre.size();
if(len == 0) return NULL;
vector<int> pre_left, pre_right, vin_left, vin_right;
int pos;
TreeNode* head = new TreeNode(pre[0]);
for(int i = 0; i < len; i++)
if(pre[0] == vin[i]){
pos = i;
break;
}
for(int i = 0; i < pos; i++){
pre_left.push_back(pre[i+1]);
vin_left.push_back(vin[i]);
}
for(int i = pos+1; i < len; i++){
pre_right.push_back(pre[i]);
vin_right.push_back(vin[i]);
}
head->left = reConstructBinaryTree(pre_left,vin_left);
head->right = reConstructBinaryTree(pre_right,vin_right);
return head;
}
};
4.旋转数组的最小数字
把一个非递减数组的前面若干个数字搬移到后面,求最小数字。比如12345,变成34512。最小数字肯定为右侧序列第一个。
非递减就是递增和都相等。递增的情况里也有01111变成10111这种情况。
利用二分查找,如果num[mid]<num[right],说明mid和right都在右侧,令right=mid;如果num[mid]>num[right],说明mid在左侧,令left=mid+1。
因为当right和left相差仅一位时,mid为left,而且right肯定一直在右侧,所以此时有可能left和right都在右侧,left为最小元素,则判断后num[mid]<num[right]会left=mid+1,则right = left;
或者left在左侧,right为最小元素,则num[mid]>num[right],right=mid,即right=left;
所以这种情况left<right可作为循环进行条件。
还有一种都相等的情况。所以还要再加个条件,如果num[mid]=num[right],right=right-1;
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
int len = rotateArray.size();
if(len == 0) return 0;
int left = 0, right = len-1;
while(left<right)
{
int mid = (left+right)/2;
if(rotateArray[right]<rotateArray[mid]) left = mid+1;
else if(rotateArray[right]>rotateArray[mid]) right = mid;
else right--;
}
return rotateArray[left];
}
};
5.斐波那契数列
class Solution {
public:
int Fibonacci(int n) {
if(n==0) return 0;
if(n==1) return 1;
int n1 = 0, n2 = 1;
for(int i = 2; i <= n; i++)
{
n2 = n1+n2;
n1 = n2-n1;
}
return n2;
}
};
6.青蛙跳台阶
一个青蛙可以跳一个台阶,也可以跳两个台阶。跳n个台阶有多少种跳法。
青蛙最后一次跳一个台阶或者两个台阶跳到n个台阶,所以f(n)=f(n-1)+f(n-2)。所以就相当于斐波那契数列。
7.类似6
如果青蛙可以跳1到n任意个台阶,问跳n个台阶共多少种跳法。
如果青蛙要跳n个台阶:
第一次跳1个台阶,剩余n-1个台阶,方法有f(n-1)种;
第一次跳2个台阶,剩余n-2个台阶,方法有f(n-2)种;
以此类推,f(n)=f(n-1)+f(n-2)+.....+f(1)+1=2f(n-1)。