剑指offer(1~10)题解

Posted amoy-zhp

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指offer(1~10)题解相关的知识,希望对你有一定的参考价值。

剑指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)

以上是关于剑指offer(1~10)题解的主要内容,如果未能解决你的问题,请参考以下文章

剑指 Offer(第 2 版)完整题解笔记 & C++代码实现(LeetCode版)

剑指 Offer 53 - I. 在排序数组中查找数字 I c++/java详细题解

乱序版 ● 剑指offer每日算法题打卡题解——动态规划 (题号10,63)

leetcode剑指offer合集+题解

leetcode剑指offer合集+题解

乱序版 ● 剑指offer每日算法题打卡题解—— 排序(题号 40,45,61)