【剑指offer系列】系列一

Deadly 提交于 2019-12-14 02:25:34

系列一:1~10题

目录

系列一:1~10题

1、二维数组中的查找【数组】

题目描述

1.1、分析

1.2、代码

2、替换空格【字符串】

题目描述

2.1、分析

2.2、代码

3、从尾到头打印链表【链表】

题目描述

3.1、分析

3.2、代码

4、重建二叉树【树】

题目描述

4.1、分析

4.2、代码

 5、用两个栈实现队列【队列】【栈】

题目描述

6.1、分析

6.2、代码

7、旋转数组的最小数字【查找】【二分】

题目描述

7.1 分析

7.2 代码

 8、斐波那契数列【动态规划】

题目描述

8.1、分析

8.2、代码

9、跳台阶【动态规划】

题目描述

9.1、分析

9.2、代码

10、变态跳台阶【动态规划】【完全背包问题】

题目描述

10.1、分析

10.2、代码

1、二维数组中的查找【数组】

题目:原题链接

题目描述

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

1.1、分析

      对于这样的数组,我们可以发现,从右上角数字开始比较,若比目标数字小,那么一定不会在第一行,所有可以跳过第一行,若比目标数字大,那么肯定不在最后一列,则可以跳过最后一列。依次这样比较下去,直到相等为止。

1.2、代码

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        if(array.empty()||array[0].empty()) return false;
        int i=0,j=array[0].size()-1;
        while(i<array.size()&&j>=0){
            if(array[i][j]==target) return true;
            else if(array[i][j]>target) j--;
            else i++;
        }
        return false;
    }
};

2、替换空格【字符串】

题目:原题链接

题目描述

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

2.1、分析

       我们可以先定义一个string类型的字符串,由于string类型可以直接用+进行字符串拼接,所以当遇到空格时,我们就加上"%20",不是空格就直接加上原先的字符,最终需要把string类型字符串copy到原字符型数组中。

2.2、代码

class Solution {
public:
	void replaceSpace(char *str,int length) {
        string res;
        for(int i=0;i<length;i++){
            if(str[i]==' ') res+="%20";
            else res+=str[i];
        }
        strcpy(str,res.c_str());
	}
};

3、从尾到头打印链表【链表】

题目:原题链接

题目描述

输入一个链表,按链表从尾到头的顺序返回一个ArrayList。

3.1、分析

        我们可以先按照链表的顺序,把值存在一个容器中,然后使用reverse对容器做一个反转,就可以实现顺序是逆向的了。

3.2、代码

/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
*/
class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        vector<int> ans;
        if(!head) return ans;
        for(auto p=head;p;p=p->next){
            ans.push_back(p->val);
        }
        reverse(ans.begin(),ans.end());
        return ans;
    }
};

4、重建二叉树【树】

题目:原题链接

题目描述

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

4.1、分析

4.2、代码

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int n,m;
    unordered_map<int,int> hash; //用于快速根据根节点值,找到在中序遍历的位置
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
        n=pre.size()-1,m=vin.size()-1;
        for(int i=0;i<=m;i++) hash[vin[i]]=i;
        return dfs(pre,vin,0,n,0,m);
    }
    TreeNode* dfs(vector<int> &pre,vector<int> &vin,int ps,int pe,int vs,int ve)
    {
        if(ps>pe) return NULL;
        int root_val=pre[ps];
        auto root=new TreeNode(root_val);
        int k=hash[root_val];
        int len=k-vs;
        root->left=dfs(pre,vin,ps+1,ps+len,vs,k-1);
        root->right=dfs(pre,vin,ps+len+1,pe,k+1,ve);
        return root;
    }
};

 5、用两个栈实现队列【队列】【栈】

题目:原题链接

题目描述

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

6.1、分析

       其实就是每次压栈时就只往其中一个栈中压入,当需要出队时,如果另一个栈是空的,我们就把数据全部弹到另一个栈中,然后取另一个栈的栈顶元素即可,若另一个栈不是空的,那么直接弹出栈顶元素即可。

6.2、代码

class Solution
{
public:
    void push(int node) {
        stack1.push(node);
    }

    int pop() {
        if(stack2.size()){ //当stack2不是空的,直接弹出栈顶元素
            int k=stack2.top();
            stack2.pop();
            return k;
        }
        else{ //若是空的,则把stack1清空,全部弹到stack2中
            while(stack1.size()){
                int k=stack1.top();
                stack1.pop();
                stack2.push(k);
            }
            int t=stack2.top(); //再取栈顶元素
            stack2.pop();
            return t;
        }
    }

private:
    stack<int> stack1;
    stack<int> stack2;
};

7、旋转数组的最小数字【查找】【二分】

题目:原题链接

题目描述

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

7.1 分析

7.2 代码

class Solution {
public:
    int minNumberInRotateArray(vector<int> num) {
        if(num.empty()) return 0;
        int l=0,r=num.size()-1;
        while(l<r){
            int mid=l+r>>1;
            if(num[mid]<=num.back()) r=mid;
            else l=mid+1;
        }
        return num[r];
    }
};

 8、斐波那契数列【动态规划】

题目:原题链接

题目描述

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

n<=39

8.1、分析

       大家应该都知道斐波那契数列,就是当前项等于前两项的和,所以我们只需要定义出第0项和第1项,然后一步步递推过去即可。

8.2、代码

class Solution {
public:
    int Fibonacci(int n) {
        int first=0,second=1,third=0;
        if(n<=1) return n;
        for(int i=2;i<=n;i++){
            third=first+second;
            first=second;
            second=third;
        }
        return third;
    }
};

9、跳台阶【动态规划】

题目:原题链接

题目描述

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

9.1、分析

        这题其实是一个特别简单的动态规划问题,我们直接考虑最后一步,最后一步到n阶台阶,可以是一步上来的,也可以是两步上来的,那么总的种数就是从一步上来的种数加上从两步上来的种数,现在子问题就变成了怎样上到n-1阶台阶和n-2阶台阶了。定义状态f[i]表示上到台阶i的种数,状态计算:f[i]=f[i-1]+f[i-2],初始状态就是f[1]=1,f[2]=2,然后依次递推下去。

9.2、代码

class Solution {
public:
    int jumpFloor(int number) {
        vector<int> f(number+1);
        f[1]=1;
        f[2]=2;
        for(int i=3;i<=number;i++){
            f[i]=f[i-1]+f[i-2];
        }
        return f[number];
    }
};

10、变态跳台阶【动态规划】【完全背包问题】

题目:原题链接

题目描述

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

10.1、分析

同样地,分析最后一步,最后一步可能是一次从n-1台阶跳过来,也可能是从n-2台阶跳过来。。。所以f[n]=f[n-1]+f[n-2]+...+f[1]然后我们发现f[n-1]=f[n-2]+f[n-3]+...+f[1],所以f[n]=2*f[n-1],初始状态f[1]=1。

10.2、代码

class Solution {
public:
    int jumpFloorII(int n) {
        //f[n]=2*f[n-1];
        vector<int> f(n+1);
        f[1]=1;
        for(int i=2;i<=n;i++)
            f[i]=2*f[i-1];
        return f[n];
    }
};

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!