其他分享
首页 > 其他分享> > 二刷剑指——壹

二刷剑指——壹

作者:互联网

文章目录

1.数组中重复的数字

找出数组中重复的数字。在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

方法1:

sort排序后,遍历数组,前面的值和后面的值相等即可

时间复杂度:nongn;

空间复杂度:快排需要递归,栈桢消耗 longn

class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        int count=0;
        for(int i=0;i<nums.size()-1;i++)
        {
            if(nums[i]==nums[i+1])
            {
                count=nums[i];
                break;
            }
        }
        return count;


    }
};

方法2:

统计排序、找出统计数组之中,值大于1的选项,然后+1返回

时间复杂度:O(n);

空间复杂度: O(n);

class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        vector<int> ret(nums.size(),0);
        for(auto &e:nums)
        {
            if(ret[e]!=0)
            return e;
            ret[e]++;
        }
        return 0;

    }
};

2.二维数组中的查找

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

在这里插入图片描述

时间复杂度:O(m*n)

空间复杂度:O(1)

class Solution {
public:
    bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) { 
        if(matrix.size()==0)
        return false;
        
        int row=0;
        int col=matrix[0].size()-1;

        while(row>=0&&row<matrix.size()&&col>=0&&col<matrix[0].size())
        {
            if(matrix[row][col]>target)
                col--;
            else if(matrix[row][col]<target)
                row++;
            else
                return true;
        }
        return false;

    }
};

3. 替换空格

请实现一个函数,把字符串 s 中的每个空格替换成"%20"。

遍历s,遇到空格,则str+=“%20”,其余情况之下,+=s[i]

【注意:先开辟好str的空间,避免发生增容,导致发生拷贝】

时间复杂度:O(n)

空间复杂度:O(n)

class Solution {
public:
    string replaceSpace(string s) {
        string str;
        str.reserve(s.size());
        for(int i=0;i<s.size();i++)
        {
            if(s[i]==' ')
            str+="%20";
            else
            str+=s[i];
        }
        return str;

    }
};

4.从尾到头打印链表

方法1:递归

链表天然具有递归属性

时间复杂度:O(N) 遍历整个链表

空间复杂度: O(N) 栈桢消耗n,返回数组n

class Solution {
public:
    void _reversePrint(ListNode* head,vector<int> &ret)
    {
        if(head==NULL)
        return ;

        _reversePrint(head->next,ret);
        ret.push_back(head->val);
    }
    vector<int> reversePrint(ListNode* head) {
        vector<int> ret;
        _reversePrint(head,ret);
        return ret;
    }
};

方法2:遍历reverse

遍历链表,将所有的内容添加至数组之中

然后将数组逆转

时间复杂度: O(N) 遍历整个链表

空间复杂度:O(N) 返回数组消耗

class Solution {
public:
    vector<int> reversePrint(ListNode* head) {
        vector<int> ret;
       ListNode* cur=head;
        while(cur)
        {
            ret.push_back(cur->val);
            cur=cur->next;
        }
        reverse(ret.begin(),ret.end());
        return ret;
 
    }
};

5.重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

在前序中找根节点,然后去中序之中寻找该根节点的位置,然后在中序之中判断该节点是否还有左右子树

时间复杂度:O(N^2):需要每次需要在中序之中遍历寻找根节点的位置

空间复杂度:O(N) 开辟N个节点空间、递归深度O(N)

class Solution {
public:
    TreeNode* _buildTree(vector<int>& preorder, vector<int>& inorder,int &prev,int &inor_begin,int &inor_end)
    {
        if(prev>=preorder.size()||inor_begin>inor_end)
            return NULL;
        
        TreeNode *root=new TreeNode(preorder[prev]);//构造根节点

        int start=inor_begin;
        while(start<inor_end)
        {
            if(inorder[start]==preorder[prev])
                break;
            start++;
        }

        int end=start-1;
        if(inor_begin<=end)//还有左区间
            root->left= _buildTree(preorder,inorder,++prev,inor_begin,end);
        else
            root->left=NULL;

        int begin=start+1;
        if(begin<=inor_end)//还有右区间
            root->right=_buildTree(preorder,inorder,++prev,begin,inor_end);
        else    
            root->right=NULL;
        
        return root;
        
    } 

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        //在前序中找根节点、找到后去中序遍历中找左右子树

        int prev=0;
        int inor_begin=0;
        int inor_end=inorder.size()-1;

        return _buildTree(preorder,inorder,prev,inor_begin,inor_end);
    }
};

6.用两个栈实现队列

定义两个栈 -> st1、st2

入数据入到栈st1,当需要出数据的时候判断st2是否为空,不为空则直接从st2之中出

为空则将st1的全部内容倒过来,然后再出数据

class CQueue {
public:
    CQueue() {}//自定义类型、自动调用构造函数
    
    void appendTail(int value) {
        st1.push(value);
    }
    
    int deleteHead() {
        if(st2.empty())
        {
            while(!st1.empty())
            {
                st2.push(st1.top());
                st1.pop();
            }
        }
        if(st2.empty())
        return -1;
        
        int val=st2.top();
        st2.pop();
        return val;
    }

    stack<int> st1;
    stack<int> st2;
};

7.斐波那契数列

方法1:递归法(超时)

方法2:三指针迭代法(first=1、second=0、third=0)

时间复杂度 :O(N)

空间复杂度:O(1)

class Solution {
public:
    int fib(int n) {

        int first=1;
        int second=0;
        int third=0;

        for(int i=0;i<n;i++)
        {
            third=(first+second)%1000000007;
            first=second;
            second=third;
        }
        return third;

    }
};

8.青蛙跳台阶问题

一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

将题目转换一下就是: 1 1 2 3 5 斐波那契数列的斐波那契数列

class Solution {
public:
    int numWays(int n) {
        // 1 1 2 3 5 斐波那契数列

        int first=0;
        int second=1;
        int third=1;

        for(int i=0;i<n;i++)
        {
            third=(second+first)%1000000007;
            first=second;
            second=third;
        }
        return third;
    }
};

9.旋转数组的最小数字

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oKb5HBSs-1620214495795)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210505165624842.png)]

class Solution {
public:
    int minArray(vector<int>& numbers) {
        int left=0;
        int right=numbers.size()-1;

        while(left<right)
        {
            int mid=left+(right-left)/2;
            
            if(numbers[mid]>numbers[right])
                left=mid+1;
            else if(numbers[mid]<numbers[right])
                right=mid;
            else//相等时
                right--;
        }
        return numbers[left];
    }
};

10.矩阵中的路径

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

深度搜索、回溯法:遍历搜索二维数组,找到第一个头节点之后,传入递归搜索函数,往四个方向进行搜索

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lMOebYOX-1620214495802)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210505154849105.png)]

标签:遍历,int,复杂度,ret,二刷,vector,数组
来源: https://blog.csdn.net/ych9527/article/details/116429097