剑指 week1

1.找出数组中重复的数字

注意点:

  • 1.有一个出现在0~n-1之外的就要返回-1
  • 2.空值返回-1
  • 3.时间复杂度O(n),空间复杂度O(1)的解法
class Solution {
public:
    int duplicateInArray(vector<int>& nums) {
        int n=nums.size();
       if(n==0)   return -1;
       for(int i=0;i<n;i++)
       {
          if(nums[i]<0||nums[i]>=n) return -1;
       }
       for(int i=0;i<n;i++)
       {
          while(nums[nums[i]]!=nums[i])swap(nums[i],nums[nums[i]]);
          if(nums[i]!=i)    return nums[i];
       }
       return -1;
    }
};

2.不修改数组找出重复的数字

分治+抽屉原理,将每个数的取值的区间[1, n]划分成[1, n/2]和[n/2+1, n]两个子区间,然后分别统计两个区间中数的个数。

class Solution {
public:
    int duplicateInArray(vector<int>& nums) {
        int l=1,r=nums.size()-1;//n+1长度的数组
        while(l<r)
        {
            int mid=l+r>>1;//[l,mid],[mid+1,r]
            int s=0;
            for(auto x:nums)    s+=x>=l&&x<=mid;
            if(s>mid-l+1)  r=mid;
            else
                    l=mid+1;
        }
        return l;
    }
};

3.二维数组中的查找

每一步会排除一行或者一列,矩阵一共有 n 行,m 列,所以最多会进行 n+m 步。所以时间复杂度是 O(n+m)。

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

4.替换空格

class Solution {
public:
    string replaceSpaces(string &str) {
        string res;
        for(auto x:str)
        {
            if(x==' ')
                res+="%20";
            else
                res+=x;
        }
        return res;
    }
};

5.从尾到头打印链表

反向迭代器涨姿势了,vector<int>(res.rbegin(),res.rend())

class Solution {
public:
    vector<int> printListReversingly(ListNode* head) {
        vector<int>res;
        while(head)
        {
            res.push_back(head->val);
            head=head->next;
        }
        return vector<int>(res.rbegin(),res.rend());
    }
};

6.重建二叉树

class Solution {
public: 
    unordered_map<int,int>mp;
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int n=preorder.size();
        for(int i=0;i<n;i++)
            mp[inorder[i]]=i;//记录中序遍历中数对应的位置
        return dfs(preorder,inorder,0,n-1,0,n-1);
    }
    TreeNode* dfs(vector<int>& pre,vector<int>& in,int pl,int pr,int il,int ir)
    {
        
        if(il>ir) return NULL;
        int k=mp[pre[pl]]-il;//中序遍历中左子树的数量
        //重构根节点
        TreeNode* root=new TreeNode(pre[pl]);
        //递归左子树
        root->left=dfs(pre,in,pl+1,pl+k,il,il+k-1);
        //递归右子树
        root->right=dfs(pre,in,pl+k+1,pr,il+k+1,ir);
        
        return root;
    }
};

7.二叉树的下一个节点

俗称树的后继,给定一棵二叉树的其中一个节点,请找出中序遍历序列的下一个节点。

    1. 如果有右子树,那么右子树最左侧结点就是答案
    1. 如果没有右子树,那么就一直往上找,直到找到当前这个点,它是它father的左子树,那么它的father就是后继
class Solution {
public:
    TreeNode* inorderSuccessor(TreeNode* p) {
        if(p->right)
        {
            p=p->right;
            while(p->left)
                p=p->left;
            return p;
        }
        while(p->father&&p==p->father->right) p=p->father;
            return p->father;
    }
};

8.用两个栈实现队列

两个栈stk与cache,一个用于存,另一个用于取或者查

class MyQueue {
public:
    stack<int>stk,cache;
    /** Initialize your data structure here. */
    MyQueue() {
        
        
    }
    
    /** Push element x to the back of queue. */
    void push(int x) {
        stk.push(x);
    }
    
    void copy(stack<int>&a,stack<int>&b)
    {
        while(a.size())
        {
            b.push(a.top());
            a.pop();
        }

    }
    
    /** Removes the element from in front of queue and returns that element. */
    int pop() {
        copy(stk,cache);
        int res=cache.top();
        cache.pop();
        copy(cache,stk);
        return res;
        
    }
    
    /** Get the front element. */
    int peek() {
        copy(stk,cache);
        int res=cache.top();
        copy(cache,stk);
        return res;
        
    }
    
    /** Returns whether the queue is empty. */
    bool empty() {
        return stk.empty();
    }
};

9.斐波那契数列

  • 面试的时候能不用递归就不用递归
class Solution {
public:
int res=0;
    int Fibonacci(int n) {
        if(n==0)    return 0;
        if(n==1||n==2)    return 1;
        return res=Fibonacci(n-1)+Fibonacci(n-2);
    }
};
  • 首选dp
class Solution {
public:
    int Fibonacci(int n) {
        int dp[n+10];
        dp[0]=0;
        dp[1]=1;
        dp[2]=1;
        for(int i=3;i<=n;i++)
        {
            dp[i]=dp[i-1]+dp[i-2];
        }
        return dp[n];
    }
};

10.矩阵中的路径

dfs+回溯,注意边界条件的顺序

class Solution {
public:
    int dx[4]={0,1,0,-1};
    int dy[4]={1,0,-1,0};
    bool hasPath(vector<vector<char>>& matrix, string &str) {
        for(int i=0;i<matrix.size();i++)
            for(int j=0;j<matrix[i].size();j++)
                if(dfs(matrix,str,0,i,j))
                    return true;
        return false;
    }
   bool dfs(vector<vector<char>>&matrix,string &str,int u,int x,int y)
    {
        if(matrix[x][y]!=str[u])    
            return false;
        if(u==str.size()-1)
            return true;
        char t=matrix[x][y];
        matrix[x][y]='*';
        for(int i=0;i<4;i++)
        {
            int a=x+dx[i],b=y+dy[i];
            if(a>=0&&a<matrix.size()&&b>=0&&b<matrix[0].size())
                if(dfs(matrix,str,u+1,a,b)) 
                    return true;
        }
        matrix[x][y]=t;
        return false;
    }
};
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容