剑指offer(1~10)
二维数组中的查找
源代码
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
for(int i = 0 ; i < array.size() ; i ++){
for( int j = array[i].size() - 1 ; j >= 0 ; j--){
if( array[i][j] == target){
return true;
} else if( target > array[i][j]) {
break;
}
}
}
return false;
}
};
解析
因为数组从左到右递增,从上到下递增,于是从矩阵右上角开始找。如果比行最后一个值大,则直接到下一行找。若比一行找,这需要找的值要么再这一行要么不在矩阵中。
替换空格
源代码
class Solution {
public:
void replaceSpace(char *str,int length) {
int cntlength = 0;
do{
cntlength++;
}while( str[cntlength] != ‘\0‘);
for(int i = 0 ; str[i] != ‘\0‘ ;){
if( str[i] == ‘ ‘){
cntlength += 2;
for(int j = cntlength + 2 ; j > i + 2 ; j--){
str[j] = str[j - 2];
}
str[i] = ‘%‘;
str[i + 1] = ‘2‘;
str[i + 2] = ‘0‘;
i = i + 3;
} else {
i++;
}
}
}
};
解析
题中给的length是字符串开辟空间的长度,不是字符串长度,需要注意一下。替换的换先计算出字符串的长度,然后找到空格后,就将相应位置的字符串后移,然后把空出来的位置替换成题目要求的字符。
从头到尾打印链表
源代码
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> list;
if( head != NULL){
while( head -> next != NULL){
list.push_back(head -> val);
head = head -> next;
}
list.push_back(head -> val);
reverse(list.begin() , list.end());
}
return list;
}
};
解析
因为返回的vector,用了vector的逆序函数完成了逆序。
重建二叉树
源代码
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
if( pre.size() == 0){
return NULL;
}
TreeNode* root = new TreeNode(pre[0]);
root -> left = NULL;
root -> right = NULL;
if( pre.size() == 1){
return root;
}
vector<int> leftpre;
vector<int> rightpre;
vector<int> leftvin;
vector<int> rightvin;
for(int i = 0 ; i < vin.size() ; i ++){
if( pre[0] == vin[i]){
leftpre.assign(pre.begin() + 1, pre.begin() + i + 1);
leftvin.assign(vin.begin(), vin.begin() + i);
rightpre.assign(pre.begin()+ i + 1 , pre.end());
rightvin.assign(vin.begin()+ i + 1, vin.end());
root -> left = reConstructBinaryTree(leftpre , leftvin);
root -> right = reConstructBinaryTree(rightpre , rightvin);
break;
}
}
return root;
}
};
解析
中序中,在根左侧的都是左子树节点,右侧的都是右子树节点,并且可以算出左子树和右子树节点的个数,因此就可以从前序中截取左子树的前序序列和右子树的前序列。这里用了递归的方法,把左子树的前序中序,右子树的前序中序作为输入又传到函数中。完成二叉树的重建。
用两个栈实现队列
源代码
class Solution
{
public:
void push(int node) {
stack1.push(node);
}
int pop() {
int temp;
if( stack2.empty()){
while( !stack1.empty()){
temp = stack1.top();
stack1.pop();
stack2.push(temp);
}
}
temp = stack2.top();
stack2.pop();
return temp;
}
private:
stack<int> stack1;
stack<int> stack2;
};
解析
因为栈是先进后出,将栈中元素取出再押入新栈,新栈的出栈顺序就变成原来的逆序,即第一个栈中先进就会先出。所以将新的元素押入到栈1中,在取元素的时候,如果栈2为空,则栈1元素出栈再押入栈2中,然后再顺序将栈2元素出栈
旋转数组中的最小数字
源代码
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
if( rotateArray.size() == 0){
return 0;
}
for(int i = 0 ; i < rotateArray.size() ; i ++){
if( rotateArray[i] > rotateArray[i + 1]){
return rotateArray[i + 1];
}
}
return 0;
}
};
解析
思路是找到的第一个元素比前面元素小的那个元素,就是要找的那个元素。不过这里的时间复杂度应该不是最小的。
斐波那契数列
源代码
class Solution {
public:
int Fibonacci(int n) {
if( n == 0)return 0;
if( n == 1)return 1;
int a1 = 1;
int a2 = 0;
int temp;
for(int i = 1 ; i < n ; i ++){
temp = a1 + a2;
a2 = a1;
a1 = temp;
}
return a1;
}
};
解析
斐波那契数列 f(n) = f(n - 1) + f(n - 2),按此规律实现即可。
跳台阶
源代码
class Solution {
public:
int jumpFloor(int number) {
if(number == 0) return 0;
if(number == 1) return 1;
if(number == 2) return 2;
int temp;
int a1 = 2;
int a2 = 1;
for(int i = 2 ; i < number ; i ++){
temp = a1 + a2;
a2 = a1;
a1 = temp;
}
return a1;
}
};
解析
其实还是斐波那契数列问题。对于第n个台阶,如果第一次跳1一个,则剩下的解法是f(n-1),如果跳两个,则剩下的解法是f(n-2),即f(n) = f(n - 1) + f(n -2);
变态跳台阶
源代码
class Solution {
public:
int jumpFloorII(int number) {
if(number == 1)return 1;
if(number == 2)return 2;
if(number == 3)return 4;
int sum = 4;
while( number >= 4){
sum *= 2;
number--;
}
return sum;
}
};
解析
这里类似上一题的解题思路,f(3) = f(2) + f(1) + 1;其中1为一次跳三个。而f(4) = f(3) + f(2) + f(1) + 1;而后面三项显然为f(3)所以f(4) = 2 * f(3);后面以此类推有f(n) = 2 *f(n - 1)
矩形覆盖
源代码
class Solution {
public:
int rectCover(int number) {
if( number == 0) return 0;
if( number == 1) return 1;
if( number == 2) return 2;
int temp;
int f1 = 2;
int f2 = 1;
for(int i = 2 ; i < number ; i ++){
temp = f1 + f2;
f2 = f1;
f1 = temp;
}
return f1;
}
};
解析
这个也是斐波那契饿数列问题
o |
---|
o |
x | x |
---|---|
o | o |
n为1时只有一种解法,n为2时有横竖两种解法,当n变大时,类似跳台阶问题,如果是纵向,则为f(n -1),如果为横向则为f(n - 2),有f(n) = f(n - 1) + f(n - 2)