zoukankan      html  css  js  c++  java
  • leetcode腾讯精选练习(50 题)(持续更新)

    1.除自身以外数组的乘积

    给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。

    示例:

    输入: [1,2,3,4]
    输出: [24,12,8,6]
    说明: 请不要使用除法,且在 O(n) 时间复杂度内完成此题。

     题解:记录前缀积和后缀积。
     
    参考代码:
    class Solution {
    public:
        vector<int> productExceptSelf(vector<int>& nums)
        {
            int siz=nums.size();
            vector<int> pre(siz+1),nxt(siz+2),ans(siz);
            pre[0]=1;nxt[siz+1]=1;
            for(int i=0;i<siz;++i)
                pre[i+1]=pre[i]*nums[i];
            for(int i=siz-1;i>=0;--i)
                nxt[i+1]=nxt[i+2]*nums[i];
            
            for(int i=1;i<=siz;++i)
                ans[i-1]=pre[i-1]*nxt[i+1];
            
            return ans;
        }
    };
    C++

     2.格雷编码

    格雷编码是一个二进制数字系统,在该系统中,两个连续的数值仅有一个位数的差异。

    给定一个代表编码总位数的非负整数 n,打印其格雷编码序列。格雷编码序列必须以 0 开头。

    示例 1:

    输入: 2
    输出: [0,1,3,2]
    解释:
    00 - 0
    01 - 1
    11 - 3
    10 - 2

    对于给定的 n,其格雷编码序列并不唯一。
    例如,[0,2,3,1] 也是一个有效的格雷编码序列。

    00 - 0
    10 - 2
    11 - 3
    01 - 1
    示例 2:

    输入: 0
    输出: [0]
    解释: 我们定义格雷编码序列必须以 0 开头。
      给定编码总位数为 n 的格雷编码序列,其长度为 2n。当 n = 0 时,长度为 20 = 1。
      因此,当 n = 0 时,其格雷编码序列为 [0]。

    题解:

    对于每一层都是上一层倒着加上2^(i-1)次方。

    参考代码:

    class Solution {
    public:
        int qpow(int n,int m)
        {
            int res=1;
            while(m)
            {
                if(m&1) res=res*n;
                n=n*n; m>>=1;
            }
            return res;
        }
        vector<int> grayCode(int n) 
        {
            vector<int> ans;
            if(n==0) 
            {
                ans.push_back(0);
                return ans;
            }
            ans.push_back(0);
            ans.push_back(1);
    
            for(int i=2;i<=n;++i)
            {
                vector<int> res=ans;
                int num=qpow(2,i-1),siz=ans.size();
                for(int j=siz-1;j>=0;--j)
                    ans.push_back(res[j]+num);
            }
    
            return ans;
        }
    };
    C++

    3.二叉树的最近公共祖先

    给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

    百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

    例如,给定如下二叉树:  root = [3,5,1,6,2,0,8,null,null,7,4]

    示例 1:

    输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
    输出: 3
    解释: 节点 5 和节点 1 的最近公共祖先是节点 3。
    示例 2:

    输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
    输出: 5
    解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。
     

    说明:

    所有节点的值都是唯一的。
    p、q 为不同节点且均存在于给定的二叉树中。

    题解:

      递归。

      两个节点要么是父子关系,要么在一个root下,我们们判断root是否为p或q,是的话,就返回root.

    然后递归左右子树,如果left!=null&&right!=null则返回root.

    如果left==null,则返回右子树的递归结果,否则返回左子树的递归结果。

    参考代码:

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) 
        {
            if(root==null) return root;
            if(root==p||root==q) return root;
            TreeNode left=lowestCommonAncestor(root.left,p,q);
            TreeNode right=lowestCommonAncestor(root.right,p,q);
            
            if(left!=null && right!=null) return root;
            if(left==null) return right;
            else return left;
        }
    }
    
    Java
    Java

     4.二叉搜索树的最近公共祖先

    给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

    百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

    例如,给定如下二叉搜索树:  root = [6,2,8,0,4,7,9,null,null,3,5]

    示例 1:

    输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
    输出: 6
    解释: 节点 2 和节点 8 的最近公共祖先是 6。
    示例 2:

    输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
    输出: 2
    解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。
     

    说明:

    所有节点的值都是唯一的。
    p、q 为不同节点且均存在于给定的二叉搜索树中。

    题解:

    可以用上一题的解法。但是根据二叉搜索树的特点,左子树的值都比我小,右子树都比我大。

    递归,3行代码解决问题。

    参考代码:

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
            if(root.val>p.val && root.val>q.val) return lowestCommonAncestor(root.left, p, q);
            if(root.val<p.val && root.val<q.val) return lowestCommonAncestor(root.right,p,q);
            return root;
        }
        
    }
    Java

     5.二叉树中的最大路径和

    给定一个非空二叉树,返回其最大路径和。

    本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。

    示例 1:

    输入: [1,2,3]

    1
    /
    2 3

    输出: 6
    示例 2:

    输入: [-10,9,20,null,null,15,7]

      -10
       /
      9  20
        /  
       15   7

    输出: 42

    题解:

    类似树形DP,记录每个节点的左右子树到节点的一条链的最大值,和当前子树任意两点间的最大值即可(注意边界条件)。

    参考代码:

    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     * };
     */
    class Solution {
    public:
        const int INF=0x3f3f3f3f;
        pair<int,int> work(TreeNode *root)
        {
            pair<int,int> p(-INF,-INF);
            if(root==NULL) return p;
            pair<int,int> l=work(root->left);
            pair<int,int> r=work(root->right);
            p.first=max(max(l.first,r.first)+root->val,root->val);
            p.second=max(max(l.second,r.second),max(root->val,max(l.first+root->val+r.first,p.first)));
            return p;
        }
        int maxPathSum(TreeNode* root) 
        {
            pair<int,int> ans=work(root);
            return ans.second;
        }
    };
    C++

    6.LRU缓存机制

     

    运用你所掌握的数据结构,设计和实现一个  LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。

    获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。
    写入数据 put(key, value) - 如果密钥不存在,则写入其数据值。当缓存容量达到上限时,它应该在写入新数据之前删除最近最少使用的数据值,从而为新的数据值留出空间。

    进阶:

    你是否可以在 O(1) 时间复杂度内完成这两种操作?

    示例:

    LRUCache cache = new LRUCache( 2 /* 缓存容量 */ );
    
    cache.put(1, 1);
    cache.put(2, 2);
    cache.get(1);       // 返回  1
    cache.put(3, 3);    // 该操作会使得密钥 2 作废
    cache.get(2);       // 返回 -1 (未找到)
    cache.put(4, 4);    // 该操作会使得密钥 1 作废
    cache.get(1);       // 返回 -1 (未找到)
    cache.get(3);       // 返回  3
    cache.get(4);       // 返回  4

    题解:

    按题意的来嘛,用MapStack就可以解决了。

    参考代码:

    class LRUCache {
     
        Map<Integer,Integer> map ;
        Stack<Integer> stack;
        int size;
        
        public LRUCache(int capacity) {
            stack = new Stack<>();
            map = new HashMap<>(capacity);
            size = capacity;
        }
        
        public int get(int key) {
            if(!stack.contains(key)){
                return -1;
            }
            boolean flag = stack.remove(Integer.valueOf(key));
            stack.push(key);
            return map.get(key);
        }
        
        public void put(int key, int value) {
            if(stack.contains(key)){
                stack.remove(Integer.valueOf(key));
            }else{
                if(stack.size() == size){
                    int count = stack.remove(0);
                    map.remove(count);
                }
            }
            stack.push(key);
            map.put(key,value);
        }
    }
    
    C++
    C++

     7.二叉搜索树中的第K小元素

    给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素。

    说明:
    你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元素个数。

    示例 1:

    输入: root = [3,1,4,null,2], k = 1
    3
    /
    1 4

      2
    输出: 1
    示例 2:

    输入: root = [5,3,6,2,4,null,null,1], k = 3
    5
    /
    3 6
    /
    2 4
    /
    1
    输出: 3

    题解:

    按照后序遍历的顺序把二叉搜索树中的元素依次加入vector<int> ans里面,然后输出ans[k-1]即是第K小元素;

    参考代码:

    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     * };
     */
    class Solution {
    public:
        void work(TreeNode* root,vector<int>&v)
        {
           if(root==NULL) return ;
           if(root->left) work(root->left,v);
           v.push_back(root->val);
            if(root->right) work(root->right,v);
        }
    
        int kthSmallest(TreeNode* root, int k) 
        {
            vector<int> ans;
            work(root,ans);
            return ans[k-1];
        }
    };
    C++

     8.NIM游戏

    你和你的朋友,两个人一起玩 Nim 游戏:桌子上有一堆石头,每次你们轮流拿掉 1 - 3 块石头。 拿掉最后一块石头的人就是获胜者。你作为先手。

    你们是聪明人,每一步都是最优解。 编写一个函数,来判断你是否可以在给定石头数量的情况下赢得游戏。

    示例:

    输入: 4
    输出: false
    解释: 如果堆中有 4 块石头,那么你永远不会赢得比赛;
      因为无论你拿走 1 块、2 块 还是 3 块石头,最后一块石头总是会被你的朋友拿走。

    题解:

    flag=n%4,判断,如果flag==0则先手必败,否则,先手必胜。

    参考代码:

    class Solution {
    public:
        bool canWinNim(int n) 
        {
            if(n%4) return true;
            else return false;
        }
    };
    C++

    未完待续~

  • 相关阅读:
    【Splay树】
    毕业设计每日总结2020/2/8
    毕业设计每日总结2020/2/7
    毕业设计每日总结2020/2/6
    毕业设计每日总结2020/2/5
    毕业设计每日总结2020/2/4
    毕业设计每日总结2020/2/3
    毕业设计每日总结2020/2/2
    毕业设计每日总结2020/2/1
    毕业设计第一周计划
  • 原文地址:https://www.cnblogs.com/csushl/p/12074694.html
Copyright © 2011-2022 走看看