LeetCode刷题记录(百度)

文章目录

    • leetcode-215.数组中的第K个最大元素
    • leetcode-206.反转链表
    • leetcode-142.环形链表II
    • leetcode-94. 二叉树的中序遍历
    • leetcode-104. 二叉树的最大深度
    • leetcode-102. 二叉树的层序遍历
    • leetcode-69. x 的平方根
    • leetcode-5. 最长回文子串
    • leetcode-62. 不同路径
    • leetcode-53. 最大子序和
    • leetcode-1143. 最长公共子序列
    • leetcode-72. 编辑距离
    • leetcode-300. 最长上升子序列
    • 剑指 Offer 47. 礼物的最大价值
    • leetcode-121. 买卖股票的最佳时机I
    • leetcode-122. 买卖股票的最佳时机 II
    • leetcode-123. 买卖股票的最佳时机 III
    • leetcode-309. 最佳买卖股票时机含冷冻期
    • leetcode-714. 买卖股票的最佳时机含手续费
    • leetcode-322. 零钱兑换
    • leetcode-199. 二叉树的右视图
    • leetcode-19. 删除链表的倒数第N个节点
    • 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
    • leetcode-543. 二叉树的直径
    • leetcode-20. 有效的括号
    • leetcode-160. 相交链表
    • leetcode-349. 两个数组的交集
    • leetcode-46. 全排列 I
    • leetcode-47. 全排列 II
    • leetcode-78. 子集
    • leetcode-39. 组合总和 I
    • leetcode-40. 组合总和 II
    • leetcode-1. 两数之和
    • leetcode-15. 三数之和
    • leetcode-16. 最接近的三数之和 (问题很多)
    • leetcode-287. 寻找重复数
    • leetcode-191. 位1的个数
    • leetcode-1143. 最长公共子序列
    • leetcode-123. 买卖股票的最佳时机 III
    • leetcode-25. K 个一组翻转链表
    • leetcod-92. 反转链表 II
    • leetcode-24. 两两交换链表中的节点
    • leetcode-121. 买卖股票的最佳时机
    • leetcode-235. 二叉搜索树的最近公共祖先
    • leetcode-236. 二叉树的最近公共祖先
    • leetcode-88. 合并两个有序数组
    • 剑指 Offer 36. 二叉搜索树与双向链表
    • leetcode-169. 多数元素
    • leetcode-110. 平衡二叉树
    • leetcode-234. 回文链表
    • leetcode-83. 删除排序链表中的重复元素
    • leetcode-876. 链表的中间结点
    • leetcode-100. 相同的树
    • leetcode-101. 对称二叉树
    • 剑指 Offer 27. 二叉树的镜像
    • leetcode-226. 翻转二叉树
    • 剑指 Offer 26. 树的子结构
    • leetcode-572. 另一个树的子树

leetcode-215.数组中的第K个最大元素

使用小顶堆,时间复杂度

class Solution {
     
    public int findKthLargest(int[] nums, int k) {
     
        if (nums == null || nums.length == 0) return 0;
        PriorityQueue<Integer> queue = new PriorityQueue<>();
        for(int i=0;i<nums.length;i++){
     
           if(queue.size()<k){
     
               queue.add(nums[i]);
           }else if(queue.peek()<nums[i]){
     
               queue.poll();
               queue.add(nums[i]);
           }
        }
        return queue.peek();
    }
}

快速排序:

class Solution {
    public int findKthLargest(int[] nums, int k) {
        if (nums == null || nums.length == 0) return 0;
        int left = 0;
        int right = nums.length-1;
        quickSort(nums,left,right);
        return nums[nums.length-k];
    }

    private void quickSort(int[] nums, int left, int right) {
        if(left>right ) return;
        int index = getIndex(nums,left,right);
        quickSort(nums,left,index-1);
        quickSort(nums,index+1,right);
    }

    private int getIndex(int[] nums, int left, int right) {
        int tmp = nums[left];
        while (left=tmp){
                right--;
            }
            nums[left] = nums[right];
            while (left

leetcode-206.反转链表

class Solution {
     
    public ListNode reverseList(ListNode head) {
     
        if(head==null) return head;
        ListNode pre = null;
        ListNode cur = head;
        while (cur!=null){
     
            ListNode tmp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = tmp;
        }
        return pre;
    }
}

leetcode-142.环形链表II

public class Solution {
     
    public ListNode detectCycle(ListNode head) {
     
        ListNode slow = head;
        ListNode fast = head;
        while (true){
     
            if(fast==null || fast.next==null){
     
                return null;
            }
            
            slow = slow.next;
            fast = fast.next.next;
            
            if(slow==fast) {
     
                break;
            }
        }
        slow = head;
        while (slow!=fast){
     
            slow = slow.next;
            fast = fast.next;
        }
        return slow;
    }
}

leetcode-94. 二叉树的中序遍历

递归算法:

class Solution {
     
    List<Integer> list = new ArrayList<>();
    public List<Integer> inorderTraversal(TreeNode root) {
     
        if(root==null) return list;
        dfs(root);
        return list;
    }

    private void dfs(TreeNode root) {
     
        if(root==null) return;
        dfs(root.left);
        list.add(root.val);
        dfs(root.right);
    }
}

迭代算法:

class Solution {
     
    List<Integer> list = new ArrayList<>();
    public List<Integer> inorderTraversal(TreeNode root) {
     
        if(root==null) return list;
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()){
     
            TreeNode node = stack.pop();
            if(node!=null){
     
                if(node.right!=null) stack.push(node.right);
                stack.push(node);
                stack.push(null);
                if(node.left!=null) stack.push(node.left);
            }else{
     
                list.add((stack.pop().val);
            }
        }
        return list;
    }
}

leetcode-104. 二叉树的最大深度

class Solution {
     
    public int maxDepth(TreeNode root) {
     
        if(root==null) return 0;
        int leftDepth = maxDepth(root.left);
        int rightDepth = maxDepth(root.right);
        return Math.max(leftDepth,rightDepth)+1;
    }
}

leetcode-102. 二叉树的层序遍历

class Solution {
     
    List<List<Integer>> res = new ArrayList<>();
    public List<List<Integer>> levelOrder(TreeNode root) {
     
        if(root==null) return res;
        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        while (!queue.isEmpty()){
     
            int len = queue.size();
            ArrayList<Integer> list = new ArrayList();
            for(int i=0;i<len;i++){
     
                TreeNode node = queue.pop();
                list.add(node.val);
                if(node.left!=null) queue.add(node.left);
                if(node.right!=null) queue.add(node.right);
            }
            res.add(list);
        }
        return res;
    }
}

leetcode-69. x 的平方根

class Solution {
     
    public int mySqrt(int x) {
     
        //一定要设置为long类型的
        long start = 1;
        long  end = x;
        while (start+1<end){
     
            long mid = (end-start)/2+start;
            if(mid*mid>=x){
     
                end = mid;
            }else{
     
                start = mid;
            }
        }
        if(end*end==x) return (int)end;
        else return (int) start;
    }
}

leetcode-5. 最长回文子串

暴力算法:

class Solution {
     
    public String longestPalindrome(String s) {
     
        if(s.length() == 0) return s;
        if(s.length()<2) return s;

        int maxLen = 1;
        int begin = 0;
        //注意的是s到达最后一个字符的前面一个字符
        for(int i=0;i<s.length()-1;i++){
     
            //j到达最后一个字符
            for(int j=i+1;j<s.length();j++){
     
                if(j-i+1>maxLen && huiwenchuan(s,i,j)){
     
                    maxLen = j-i+1;
                    begin = i;
                }
            }
        }
        return s.substring(begin,begin+maxLen);
    }

    private boolean huiwenchuan(String s,int i, int j) {
     
        //abccba
        while (i<j){
     
            if(s.charAt(i)!=s.charAt(j)){
     
                return false;
            }
            i++;
            j--;
        }
        return true;
    }
}

动态规划:

class Solution {
     
    public String longestPalindrome(String s) {
     
        if(s.length()==0) return s;
        boolean[][] dp = new boolean[s.length()][s.length()];

        int maxLen = 0;
        int begin = 0;
        for(int j=0;j<s.length();j++){
     
            for(int i=0;i<=j;i++){
     
                dp[i][j]=s.charAt(i)==s.charAt(j) && (j-i<=2 || dp[i+1][j-1]);
                if(dp[i][j] && j-i+1>maxLen){
     
                    maxLen = j-i+1;
                    begin = i;
                }
            }
        }
        return s.substring(begin,begin+maxLen);
    }
}

leetcode-62. 不同路径

class Solution {
     
    public int uniquePaths(int m, int n) {
     
        //动态规划:自底向上
        //dp[i][j]代表从路径(0,0)到(i,j)的路径数
        int[][] dp = new int[m][n];
        //初始化第一行
        for(int i=0;i<n;i++){
     
            dp[0][i] = 1;
        }
        //初始化第一列
        for(int j=0;j<m;j++){
     
            dp[j][0] = 1;
        }

        for(int i=1;i<m;i++){
     
            for(int j=1;j<n;j++){
     
                //路径是只能向下走和向右走,那么路径的总数就是左边一格的路径数+上边一格的路径数
                //因为与 dp[i-1][j]+ dp[i][j-1]有关,因此需要初始化dp[0][j]和dp[i][0]
                dp[i][j] =  dp[i-1][j]+ dp[i][j-1];
            }
        }
        return dp[m-1][n-1];
    }
}

leetcode-53. 最大子序和

class Solution {
     
    public int maxSubArray(int[] nums) {
     
        //一般情况下,求最值的问题,都可转换为最优子结构来解决
        if(nums.length==0) return 0;

        int[] dp = new int[nums.length];
        //dp[i]代表前i个字符组成的子数组的最大和
        //状态转移:当前这个状态是怎么由前一个状态得到的?
        int res = nums[0];
        dp[0] = nums[0];
        for(int i=1;i<nums.length;i++){
     
            //注意到dp[i]与dp[i-1]有关,因此需要初始化dp[0]
            dp[i] = Math.max(dp[i-1]+nums[i],nums[i]);
            res = Math.max(res,dp[i]);
        }
        return res;
    }
}

leetcode-1143. 最长公共子序列

class Solution {
     
    public int longestCommonSubsequence(String text1, String text2) {
     
        if(text1==null || text2==null) return 0;
        int m = text2.length();
        int n = text1.length();
        //dp[i][j]代表text1的前i个字符和text2的前j个字符的最长公共子序列
        int[][] dp = new int[m+1][n+1];
        dp[0][0] = 0;
        for(int i=1;i<=m;i++){
     
            for(int j=1;j<=n;j++){
     
                if(text1.charAt(j-1)==text2.charAt(i-1)){
     
                    //写到这儿就要考虑初始化的问题了,初始化dp[0][0]=0;
                    dp[i][j] = dp[i-1][j-1]+1;
                }else{
     
                    //写到这儿需要初始化第一行和第一列
                    dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
                }
            }
        }
        return dp[m][n];
    }
}

leetcode-72. 编辑距离

class Solution {
     
    public int minDistance(String word1, String word2) {
     
        //这种题关键在于如何填表,你是怎么填的?先横向填再纵向填,还是先纵向填再横向填

        //dp[i][j]代表word1的前i的字符,转成word2的前j个字符需要的最小操作数
        int m = word1.length();
        int n = word2.length();
        int[][] dp = new int[m+1][n+1];
        
        //初始化第一行
        for (int i=0;i<=n;i++){
     
            dp[0][i] = i;
        }
        
        //初始化第一列
        for(int i=0;i<=m;i++){
     
            dp[i][0] = i;
        }

        for(int i=1;i<=m;i++){
     
            for(int j=1;j<=n;j++){
     
                if(word1.charAt(i-1)==word2.charAt(j-1)){
     
                    //写到这儿,去初始化dp[0][0]
                    dp[i][j] = dp[i-1][j-1];
                }else{
     
                    //写到这儿去初始化第一行和第一列dp[0][j] 和dp[i][0]
                    dp[i][j] = Math.min(Math.min(dp[i-1][j-1],dp[i-1][j]),dp[i][j-1])+1;
                }
            }
        }
        return dp[m][n];
    }
}

leetcode-300. 最长上升子序列

class Solution {
     
    public int lengthOfLIS(int[] nums) {
     
        if(nums.length==0) return 0;
        int[] dp = new int[nums.length];
        int res = 0;
        for(int i=0;i<nums.length;i++){
     
            dp[i] = 1;
            for(int j=0;j<i;j++){
     
                if(nums[i]>nums[j]){
     
                	//注意这儿,容易出错: 2 5 3 7 101 18
                    dp[i] = Math.max(dp[i],dp[j]+1);
                }
            }
            res = Math.max(res,dp[i]);
        }
        return res;
    }
}

剑指 Offer 47. 礼物的最大价值

class Solution {
     
    public int maxValue(int[][] grid) {
     
        int m = grid.length;
        int n = grid[0].length;

        int[][] dp = new int[m][n];

        //初始化第一行,只能向右走
        for(int i=1;i<m;i++){
     
            dp[i][0] = dp[i-1][0]+grid[i][0];
        }

        //初始化第一列,只能向下走
        for(int i=1;i<n;i++){
     
            dp[0][i] = dp[0][i-1]+grid[0][i];
        }

        for(int i=1;i<m;i++){
     
            for(int j=1;j<n;j++){
     
                //写到这儿去初始第一行和第一列
                dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1])+grid[i][j];
            }
        }
        return grid[m-1][n-1];
    }
}

leetcode-121. 买卖股票的最佳时机I

无后向性是指 以前出现状态 和 以前状态的变化过程 不会影响 将来的变化。

dp是自底向上的,因此需要由下面的状态得出当前的状态,也就是说分析前面一个状态到当前状态需要怎么办?

class Solution {
     
    public int maxProfit(int[] prices) {
     
        if(prices.length==0) return 0;
        // dp[i][j]代表第i天,股票状态为j时,股票的最大价格
        // j=0时代表持股(只能一次买入,因此不能卖出后买入),j=1时代表不持股
        int[][] dp = new int[prices.length][2];
        dp[0][0] = -prices[0];
        dp[0][1] = 0;
        for(int i=1;i<prices.length;i++){
     
            dp[i][0] = Math.max(dp[i-1][0],-prices[i]);
            dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0]+prices[i]);
        }
        return dp[prices.length-1][1];
    }
}

leetcode-122. 买卖股票的最佳时机 II

class Solution {
     
    public int maxProfit(int[] prices) {
     
        if(prices.length==0) return 0;

        //dp[i][j]代表第i天时持股状态为j时的最大收益,j=0时代表持股,j=1时代表不持股
        int[][] dp = new int[prices.length][2];
        dp[0][0] = -prices[0];
        dp[0][1] = 0;

        for(int i=1;i<prices.length;i++){
     
            dp[i][0] = Math.max(dp[i-1][0],dp[i-1][1]-prices[i]);
            dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0]+prices[i]);
        }
        return dp[prices.length-1][1];
    }
}

leetcode-123. 买卖股票的最佳时机 III

class Solution {
     
    public int maxProfit(int[] prices) {
     
        if(prices.length==0) return 0;
        //dp[i][j]:第i天持股状态为j时的最大利益,j=0代表第一次持股,j=1代表第一次不持股,j=2代表第二次持股,j=3代表第二次不持股
        int[][] dp = new int[prices.length][4];

        dp[0][0] = -prices[0];
        dp[0][1] = 0;
        dp[0][2] = -prices[0];
        dp[0][3] = 0;

        for(int i=1;i<prices.length;i++){
     
            dp[i][0] = Math.max(dp[i-1][0],-prices[i]);
            dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0]+prices[i]);
            dp[i][2] = Math.max(dp[i-1][2],dp[i-1][1]-prices[i]);
            dp[i][3] = Math.max(dp[i-1][3],dp[i-1][2]+prices[i]);
        }
        return Math.max(dp[prices.length-1][1],dp[prices.length-1][3]);
    }
}

模仿0-1背包优化空间复杂度:倒着写可以通过

class Solution {
     
    public int maxProfit(int[] prices) {
     
        if(prices.length==0) return 0;
        //dp[i][j]:第i天持股状态为j时的最大利益,j=0代表第一次持股,j=1代表第一次不持股,j=2代表第二次持股,j=3代表第二次不持股
        int[] dp = new int[4];

        dp[0] = -prices[0];
        dp[1] = 0;
        dp[2] = -prices[0];
        dp[3] = 0;

        for(int i=1;i<prices.length;i++){
     
            dp[3] = Math.max(dp[3],dp[2]+prices[i]);
            dp[2] = Math.max(dp[2],dp[1]-prices[i]);
            dp[1] = Math.max(dp[1],dp[0]+prices[i]);
            dp[0] = Math.max(dp[0],-prices[i]);
        }
        return Math.max(dp [1],dp[3]);
    }
}

发现正着写也能通过:

class Solution {
     
    public int maxProfit(int[] prices) {
     
        if(prices.length==0) return 0;
        //dp[i][j]:第i天持股状态为j时的最大利益,j=0代表第一次持股,j=1代表第一次不持股,j=2代表第二次持股,j=3代表第二次不持股
        int[] dp = new int[4];

        dp[0] = -prices[0];
        dp[1] = 0;
        dp[2] = -prices[0];
        dp[3] = 0;

        for(int i=1;i<prices.length;i++){
     
            dp[0] = Math.max(dp[0],-prices[i]);
            dp[1] = Math.max(dp[1],dp[0]+prices[i]);
            dp[2] = Math.max(dp[2],dp[1]-prices[i]);
            dp[3] = Math.max(dp[3],dp[2]+prices[i]);
        }
        return Math.max(dp [1],dp[3]);
    }
}

leetcode-309. 最佳买卖股票时机含冷冻期

class Solution {
     
    public int maxProfit(int[] prices) {
     
        if(prices.length==0) return 0;
        //dp[i][j]代表在第i天股票状态为j时的最大收益,j=0代表持股,j=1代表冷冻,j=2代表不持股
        int[][] dp = new int[prices.length][3];
        dp[0][0] = -prices[0];

        for(int i=1;i<prices.length;i++){
     
            // dp[i][0] = Math.max(dp[i-1][0],Math.max(-prices[i],dp[i-1][2]-prices[i]));
            // 因为支持多次买入和卖出,因此可以写成下面,可以不用细分第一次买入和第二次买入
            dp[i][0] = Math.max(dp[i-1][0],dp[i-1][2]-prices[i]);
            dp[i][1] = dp[i-1][0]+prices[i];
            dp[i][2] = Math.max(dp[i-1][2],dp[i-1][1]);
        }
        return Math.max(dp[prices.length-1][1],dp[prices.length-1][2]);
    }
}

leetcode-714. 买卖股票的最佳时机含手续费

class Solution {
     
    public int maxProfit(int[] prices, int fee) {
     
        if(prices.length==0) return 0;
        int[][] dp = new int[prices.length][2];
        //如果是买入时减去费用: dp[0][0] = -prices[0]-fee
        dp[0][0] = -prices[0];
        dp[0][1] = 0;
        for(int i=1;i<prices.length;i++){
     
            dp[i][0]= Math.max(dp[i-1][0],dp[i-1][1]-prices[i]);
            //费用可以在买入时减去,也可以在卖出时减去,上一个状态为卖出时不需要扣除手续费,仔细分析
            dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0]+prices[i]-fee);
        }
        return dp[prices.length-1][1];
    }
}

leetcode-322. 零钱兑换

class Solution {
     
    public int coinChange(int[] coins, int amount) {
     
        if(coins.length==0) return 0;
        int[] dp = new int[amount+1];
        dp[0] = 0;
        for(int i=1;i<=amount;i++){
     
            dp[i]  = amount+1;
            for(int j=0;j<coins.length;j++){
     
                //别忘记等于号
                if(i>=coins[j]){
     
                    //做到这儿需要给dp[i-coins[j]赋初值,不然会数组越界
                    dp[i] = Math.min(dp[i-coins[j]]+1,dp[i]);
                }
            }
        }
        return dp[amount]==amount+1?-1:dp[amount];
    }
}

leetcode-199. 二叉树的右视图

BFS:

class Solution {
     
    List<Integer> res = new ArrayList<>();
    public List<Integer> rightSideView(TreeNode root) {
     
        if(root==null) return res;
        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        while (!queue.isEmpty()){
     
            int len = queue.size();
            for(int i=0;i<len;i++){
     
                TreeNode node = queue.poll();
                if(i==len-1){
     
                    res.add(node.val);
                }
                if(node.left!=null) queue.add(node.left);
                if(node.right!=null) queue.add(node.right);
            }
        }
        return res;
    }
}

DFS:

class Solution {
     
    List<Integer> res = new ArrayList<>();
    public List<Integer> rightSideView(TreeNode root) {
     
        if(root==null) return res;
        dfs(root,0);
        return res;
    }

    private void dfs(TreeNode root, int level) {
     
        if(root==null) return;
        //每一层中止加入一个节点,层数增加时,res里面存放的元素的值也在增加
        //当层数和res的大小相等时,说明这一层的元素还没有添加进去
        if(res.size()==level){
     
            res.add(root.val);
        }
        //添加完之后让level增加
        level++;
        dfs(root.right,level);
        dfs(root.left,level);
    }
}

leetcode-19. 删除链表的倒数第N个节点

class Solution {
     
    public ListNode removeNthFromEnd(ListNode head, int n) {
     
        ListNode dummy = new ListNode(0);
        ListNode fast = dummy;
        ListNode slow = dummy;
        dummy.next = head;
       
        for(int i=0;i<n;i++){
     
            if(fast==null) return null;
            fast = fast.next;
        }
        
        while (fast.next!=null){
     
            fast = fast.next;
            slow = slow.next;
        }
        slow.next = slow.next.next;
        return dummy.next;
    }
}

剑指 Offer 21. 调整数组顺序使奇数位于偶数前面

leetcode不需要保证稳定性:

class Solution {
     
    public int[] exchange(int[] nums) {
     
        if(nums.length==0) return new int[0];
        int left = 0;
        int right = nums.length-1;
        while (left<right){
     
            while (left<right && nums[left]%2==1) left++;
            while (left<right && nums[right]%2==0) right--;
            int tmp =  nums[left];
            nums[left] = nums[right];
            nums[right] = tmp;
        }
        return nums;
    }
}

剑指Offer需要保证稳定性,用插入排序:

public class Solution {
     
    public void reOrderArray(int [] array) {
     
        if(array.length==0 || array==null) return;
        for(int i=1;i< array.length;i++){
     
            int insertValue = array[i];
            if(array[i]%2==1){
     
                int insertIndex = i;
                while (insertIndex>=1 && array[insertIndex-1]%2==0){
     
                    array[insertIndex] = array[insertIndex-1];
                    insertIndex--;
                }
                array[insertIndex] = insertValue;
            }
        }
    }
}

leetcode-543. 二叉树的直径

class Solution {
     
    int maxDepth = 0;
    public int diameterOfBinaryTree(TreeNode root) {
     
        if(root==null) return 0;
        dfs(root);
        return maxDepth;
    }
    private int dfs(TreeNode root) {
     
        if(root==null) return 0;
        int leftDepth = dfs(root.left);
        int rightDepth = dfs(root.right);
        maxDepth = Math.max(maxDepth,leftDepth+rightDepth);
        return Math.max(leftDepth,rightDepth)+1;
    }
}

leetcode-20. 有效的括号

class Solution {
     
    public boolean isValid(String s) {
     
        //'(',')','{','}','[',']'
        if(s.length()==0) return false;
        Stack<Character> stack = new Stack<>();
        for(int i=0;i<s.length();i++){
     
            if(s.charAt(i)=='('){
     
                stack.push(')');
            }else if(s.charAt(i)=='['){
     
                stack.push(']');
            }else if(s.charAt(i)=='{'){
     
                stack.push('}');
            }else {
     
                if(stack.isEmpty()){
     
                    return false;
                }
                if(stack.pop()!=s.charAt(i)){
     
                    return false;
                }
            }
        }
        return stack.isEmpty();
    }
}

leetcode-160. 相交链表

public class Solution {
     
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
     
        if(headA==null || headB==null) return null;
        ListNode cur1 = headA;
        ListNode cur2 = headB;
        while (cur1!=cur2){
     
            if(cur1==null){
     
                cur1 = headB;
            }else{
     
                cur1 = cur1.next;
            }

            if(cur2==null){
     
                cur2 = headA;
            }else {
     
                cur2 = cur2.next;
            }
        }
        return cur1;
    }
}

leetcode-349. 两个数组的交集

一开始想到的暴力方法:

class Solution {
     
    public int[] intersection(int[] nums1, int[] nums2) {
     
        if(nums1.length==0 || nums2.length==0) return new int[0];
        HashSet<Integer> set = new HashSet<>();
        for(int i=0;i<nums2.length;i++){
     
            for(int j=0;j<nums1.length;j++){
     
                if(nums1[j]==nums2[i]){
     
                    set.add(nums1[j]);
                }
            }
        }
        int[] arr = new int[set.size()];
        int index = 0;
        for(Integer value:set){
     
            arr[index++] = value;
        }
        return arr;
    }
}

使用两个Hashset进行优化:判断一个集合中是否含有另一个数组中的元素

看到去重应该首先想到HashSet,判断是否包含也应该想到Hashset和HashMap

class Solution {
     
    public int[] intersection(int[] nums1, int[] nums2) {
     
        if(nums1.length==0 || nums2.length==0) return new int[0];
        HashSet<Integer> set = new HashSet<>();
        HashSet<Integer> set1 = new HashSet<>();
        for(int i=0;i<nums1.length;i++){
     
            set.add(nums1[i]);
        }
        
        for(int j=0;j<nums2.length;j++){
     
            if(set.contains(nums2[j])){
     
                set1.add(nums2[j]);
            }
        }
        int[] arr = new int[set1.size()];
        int index = 0;
        for(Integer value:set1){
     
            arr[index++] = value;
        }
        return arr;
    }
}

leetcode-46. 全排列 I

class Solution {
     
    List<List<Integer>> res = new ArrayList<>();
    public List<List<Integer>> permute(int[] nums) {
     
        if(nums.length==0 || nums==null) return res;
        boolean[] used = new boolean[nums.length];
        dfs(nums,used,new ArrayList<Integer>());
        return res;
    }

    private void dfs(int[] nums, boolean[] used, ArrayList<Integer> path) {
     
        if(nums.length==path.size()){
     
            res.add(new ArrayList<>(path));
            return;
        }
        for(int i=0;i<nums.length;i++){
     
            if(used[i]) continue;
            
            path.add(nums[i]);
            used[i] = true;
            
            dfs(nums,used,path);
            
            path.remove(path.size()-1);
            used[i] = false;
        }
    }
}

leetcode-47. 全排列 II

 class Solution {
     
    List<List<Integer>> res = new ArrayList<>();
    public List<List<Integer>> permuteUnique(int[] nums){
     
        if(nums.length==0 || nums==null) return res;
        Arrays.sort(nums);
        boolean[] used = new boolean[nums.length];
        dfs(nums,used,new ArrayList<Integer>());
        return res;
    }

    private void dfs(int[] nums, boolean[] used, ArrayList<Integer> path) {
     
        if(nums.length==path.size()){
     
            res.add(new ArrayList<>(path));
            return;
        }
        for(int i=0;i<nums.length;i++){
     
            if(used[i]) continue;
            
            if(i>0 && nums[i-1]==nums[i] && used[i-1]==false) continue;

            path.add(nums[i]);
            used[i] = true;

            dfs(nums,used,path);

            path.remove(path.size()-1);
            used[i] = false;
        }
    }
}

leetcode-78. 子集

class Solution {
     
    List<List<Integer>> res = new ArrayList<>();
    public List<List<Integer>> subsets(int[] nums) {
     
        dfs(nums,new ArrayList<Integer>(),0);
        return res;
    }

    private void dfs(int[] nums, ArrayList<Integer> path, int start) {
     
        res.add(new ArrayList<>(path));
        for(int i=start;i<nums.length;i++){
     
            path.add(nums[i]);
            //注意是i+1,而不是start+1
            dfs(nums,path,i+1);
            path.remove(path.size()-1);
        }
    }
}

leetcode-39. 组合总和 I

class Solution {
     
    List<List<Integer>> res = new ArrayList<>();
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
     
        Arrays.sort(candidates);
        dfs(candidates,new ArrayList<Integer>(),target,0);
        return res;
    }

    private void dfs(int[] candidates, ArrayList<Integer> path, int target, int start) {
     
        if(target==0){
     
            res.add(new ArrayList<>(path));
            return;
        }
        for(int i=start;i<candidates.length;i++){
     
            if(candidates[i]>target) continue;
            path.add(candidates[i]);
            target = target-candidates[i];

            //里面的数可以重复利用,又因为不能出现223和232这种情况,所以为i,而不是i+1
            dfs(candidates,path,target,i);

            path.remove(path.size()-1);
            target = target+candidates[i];
        }
    }
}

leetcode-40. 组合总和 II

class Solution {
     
    List<List<Integer>> res = new ArrayList<>();
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
     
        if(candidates==null ||candidates.length==0) return res;
        Arrays.sort(candidates);
        boolean[] used = new boolean[candidates.length];
        dfs(candidates,used,new ArrayList<Integer>(),0,target);
        return res;
    }

    private void dfs(int[] candidates, boolean[] used, ArrayList<Integer> path, int start,int target) {
     
        if(target==0) {
     
            res.add(new ArrayList<>(path));
            return;
        }

        for(int i=start;i<candidates.length;i++){
     
            //每一个数上一层使用后下一层就不能再使用
            if(target<candidates[i]) continue;

            //防止数组中有重复元素
            if(used[i]) continue;
            if(i>0 && candidates[i]==candidates[i-1] && used[i-1]==false) continue;

            path.add(candidates[i]);
            target = target-candidates[i];
            used[i] = true;

            //i+1可以防止重复利用一个元素,但是其实上面已经保证了,可以使用i和i+1
            dfs(candidates,used,path,i+1,target);

            path.remove(path.size()-1);
            target= target+candidates[i];
            used[i] = false;
        }
    }
}

leetcode-1. 两数之和

class Solution {
     
    public int[] twoSum(int[] nums, int target) {
     
        if(nums.length==0) return new int[0];
        HashMap<Integer,Integer> map = new HashMap<>();
        for(int i=0;i<nums.length;i++){
     
            if(map.containsKey(target-nums[i])){
     
                return new int[]{
     i,map.get(target-nums[i])};
            }else{
     
                map.put(nums[i],i);
            }
        }
        return new int[0];
    }
}

leetcode-15. 三数之和

class Solution {
     
    List<List<Integer>> res = new ArrayList<>();
    public List<List<Integer>> threeSum(int[] nums) {
     
        if(nums.length==0) return res;
        Arrays.sort(nums);
        for(int i=0;i<nums.length;i++){
     
            if(nums[i]>0) continue;
            //比如:-4,-4,-1,-1,0,1,1,2
            if(i>0 && nums[i]==nums[i-1]) continue;
            int left = i+1;
            int right = nums.length-1;
            int sum = 0;
            while (left<right){
     
                sum = nums[left]+nums[right]+nums[i];
                if(sum==0){
     
                    res.add(Arrays.asList(nums[left],nums[right],nums[i]));
                    while (left<right && nums[left] == nums[left+1]) left++;
                    while (left<right && nums[right] == nums[right-1]) right--;
                    left++;
                    right--;
                }else if(sum>0){
     
                    right--;
                }else {
     
                    left++;
                }
            }
        }
        return res;
    }
}

leetcode-16. 最接近的三数之和 (问题很多)

class Solution {
     
    public int threeSumClosest(int[] nums, int target) {
     
        if(nums.length==0) return 0;
        Arrays.sort(nums);
        int res = nums[0]+nums[1]+nums[2];
        int sum = 0;
        for(int i=0;i<nums.length;i++){
     
            int left = i+1;
            int right = nums.length-1;

            while (left<right){
     
                sum = nums[left]+nums[right]+nums[i];
                if(sum<target){
     
                   left++;
                }else{
     
                    right--;
                }
                if(Math.abs(target-sum)<Math.abs(target-res)){
     
                    res = sum;
                }
            }
        }
        return res;
    }
}

leetcode-287. 寻找重复数

class Solution {
     
    public int findDuplicate(int[] nums) {
     
        if(nums.length==0) return 0;
        int i=0;
        while (i<nums.length){
     
            if(nums[i]==i){
     
                i++;
                continue;
            }else{
     
                int temp = nums[i];
                nums[i] = nums[temp];
                nums[temp] = temp;
            }
            if(nums[i]==nums[nums[i]]) return nums[i];
        }
        return -1;
    }
}

leetcode-191. 位1的个数

public class Solution {
     
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
     
        int res = 0;
        while (n!=0){
     
            res += n&1;
            n = n>>>1;
        }
        return res;
    }
}

leetcode-1143. 最长公共子序列

class Solution {
     
    public int longestCommonSubsequence(String text1, String text2) {
     
        int m = text2.length();
        int n = text1.length();
        int[][] dp = new int[m+1][n+1];
        dp[0][0] = 0;
        for(int i=1;i<=m;i++){
     
            for(int j=1;j<=n;j++){
     
                if(text1.charAt(j-1)==text2.charAt(i-1)){
     
                    dp[i][j] = dp[i-1][j-1]+1;
                }else{
     
                    dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
                }
            }
        }
        return dp[m][n];
    }
}

leetcode-123. 买卖股票的最佳时机 III

class Solution {
     
    public int maxProfit(int[] prices) {
     
        if(prices.length==0) return 0;
        
        int[][] dp = new int[prices.length][4];
        dp[0][0] = -prices[0];
        dp[0][1] = 0;
        dp[0][2] = -prices[0];
        dp[0][3] = 0;
        
        for(int i=1;i<prices.length;i++){
     
            dp[i][0] = Math.max(dp[i-1][0],-prices[i]);
            dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0]+prices[i]);
            dp[i][2] = Math.max(dp[i-1][2],dp[i-1][1]-prices[i]);
            dp[i][3] = Math.max(dp[i-1][3],dp[i-1][2]+prices[i]);
        }
        return Math.max( dp[prices.length-1][1], dp[prices.length-1][3]);
    }
}

leetcode-25. K 个一组翻转链表

class Solution {
     
    public ListNode reverseKGroup(ListNode head, int k) {
     
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode pre = dummy;
        ListNode end = dummy;
        
        while (end.next!=null){
     
            for(int i=0;i<k && end!=null;i++) end = end.next;
            if(end==null) break;
            ListNode start = pre.next;
            ListNode next = end.next;
            end.next = null;
            pre.next = reverseList(start);
            start.next = next;
            pre = start;
            end = pre;
        }
        return dummy.next;
    }

    private ListNode reverseList(ListNode start) {
     
        ListNode pre = null;
        ListNode cur = start;
        while (cur!=null){
     
            ListNode tmp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = tmp;
        }
        return pre;
    }
}

leetcod-92. 反转链表 II

这种方法相当于是两两的反转链表:

class Solution {
     
    public ListNode reverseBetween(ListNode head, int m, int n) {
     
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode p1 = dummy;
        ListNode p2 = head;
        for(int i=0;i<m-1;i++){
     
            p1 = p1.next;
            p2 = p2.next;
        }
        ListNode cur = null;
        for(int i=0;i<n-m;i++){
     
            cur = p2.next;
            p2.next = p2.next.next;
            cur.next = p1.next;
            p1.next = cur;
        }
        return dummy.next;
    }
}
class Solution {
     
    public ListNode reverseBetween(ListNode head, int m, int n) {
     
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode cur = dummy;
        ListNode start = head;
        for(int i=0;i<m-1;i++){
     
            cur = cur.next;
            start = start.next;
        }

        for(int i=0;i<n-m;i++){
     
           ListNode end = start.next;
           ListNode nextStart = start.next.next;
           start.next = nextStart;
           end.next =  cur.next;
           cur.next = end;
        }
        return dummy.next;
    }
}

leetcode-24. 两两交换链表中的节点

class Solution {
     
    public ListNode swapPairs(ListNode head) {
     
        if(head==null || head.next==null) return head;
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode cur = dummy;
        ListNode start = head;
        while (start !=null && start.next !=null){
     
            ListNode end = start.next;
            //必须将这个定义出来
            ListNode nexeStart = start.next.next;
            cur.next = end;
            end.next = start;
            start.next= nexeStart;
            
            //一定是先让cur=start
            cur = start;
            start = nexeStart;
        }
        return dummy.next;
    }
}

leetcode-121. 买卖股票的最佳时机

动态规划:

class Solution {
     
    public int maxProfit(int[] prices) {
     
        if(prices.length==0) return 0;
        int[] dp = new int [2];
        dp[0] = -prices[0];
        dp[1] = 0;
        for(int i=1;i<prices.length;i++){
     
            dp[0] = Math.max(dp[0],-prices[i]);
            dp[1] = Math.max(dp[1],dp [0]+prices[i]);
        }
        return dp [1];
    }
}

贪心算法:

class Solution {
     
    public int maxProfit(int[] prices) {
     
        if(prices.length==0) return 0;
        int profit = 0;
        int minPrice =prices[0];
        for(int i=0;i<prices.length;i++){
     
            if(prices[i]<minPrice){
     
                minPrice = prices[i];
            }
            profit = Math.max(profit,prices[i]-minPrice);
        }
        return profit;
    }
}

leetcode-235. 二叉搜索树的最近公共祖先

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root.valp.val && root.val>q.val) return lowestCommonAncestor(root.left,p,q);
        return root;
    }
}

leetcode-236. 二叉树的最近公共祖先

class Solution {
     
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
     
        if(root==null || root==p || root==q) return root;
        TreeNode left = lowestCommonAncestor(root.left,p,q);
        TreeNode right = lowestCommonAncestor(root.right,p,q);
        if(root==null && right==null) return null;
        if(left==null) return right;
        if(right==null) return left;
        return root;
    }
}

leetcode-88. 合并两个有序数组

class Solution {
     
    public void merge(int[] nums1, int m, int[] nums2, int n) {
     
        int i = m-1;
        int j = n-1;
        int k = m+n-1;
        while (i>=0 && j>=0){
     
            if(nums1[i]>=nums2[j]){
     
                nums1[k--] = nums1[i--];
            }else{
     
                nums1[k--] = nums2[j--];
            }
        }
        while (j>=0){
     
            nums1[k--] = nums2[j--];
        }
    }
}

剑指 Offer 36. 二叉搜索树与双向链表

class Solution {
     
    Node head;
    Node pre;
    public Node treeToDoublyList(Node root) {
     
        if(root==null) return null;
        dfs(root);
        head.left = pre;
        pre.right = head;
        return head;
    }

    private void dfs(Node cur) {
     
        if(cur==null) return;
        dfs(cur.left);
        if(pre==null){
     
            head = cur;
        }else{
     
            pre.right = cur;
        }
        cur.left = pre;
        pre = cur;
        dfs(cur.right);
    }
}

leetcode-169. 多数元素

class Solution {
    public int majorityElement(int[] nums) {
        int mainNum = 0;
        int count = 0;
        for(int i=0;i

leetcode-110. 平衡二叉树

class Solution {
     
    public boolean isBalanced(TreeNode root) {
     
        if(root==null) return true;
        dfs(root);
        return Math.abs(dfs(root.left)-dfs(root.right))<=1 && isBalanced(root.left) && isBalanced(root.right);
    }

    private int dfs(TreeNode root) {
     
        if(root==null) return 0;
        int leftDepth = dfs(root.left);
        int rightDepth = dfs(root.right);
        return Math.max(leftDepth,rightDepth)+1;
    }
}

leetcode-234. 回文链表

class Solution {
     
    public boolean isPalindrome(ListNode head) {
     
        if(head==null) return true;
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode fast = dummy;
        ListNode slow = dummy;
        while (fast!=null && fast.next!=null){
     
            fast = fast.next.next;
            slow = slow.next;
        }
        ListNode cur = slow.next;
        slow.next = null;

        ListNode pre= null;
        while (cur!=null){
     
            ListNode tmp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = tmp;
        }

        slow = head;
        while (pre!=null && slow!=null){
     
            if(pre.val==slow.val){
     
                pre = pre.next;
                slow = slow.next;
            }else{
     
                return false;
            }
        }
        return true;
    }
}

leetcode-83. 删除排序链表中的重复元素

class Solution {
     
    public ListNode deleteDuplicates(ListNode head) {
     
        if(head==null) return null;
        ListNode cur = head;
        //只需要保证cur.next!=null即可,不需要cur.nxt.next!=null否则最后两个重复的元素删不掉
        while (cur.next!=null){
     
            if(cur.val == cur.next.val){
     
                cur.next = cur.next.next;
            }else{
     
                cur = cur.next;
            }
        }
        return head;
    }
}

leetcode-876. 链表的中间结点

class Solution {
     
    public ListNode middleNode(ListNode head) {
     
        if(head==null) return head;
        ListNode fast = head;
        ListNode slow = head;
        while (fast!=null && fast.next!=null){
     
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow;
    }
}

leetcode-100. 相同的树

class Solution {
     
    public boolean isSameTree(TreeNode p, TreeNode q) {
     
        if(p==null && q==null) return true;
        if(p==null || q==null) return false;
        return p.val==q.val && isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
    }
}

leetcode-101. 对称二叉树

class Solution {
     
    public boolean isSymmetric(TreeNode root) {
     
        if(root==null) return true;
        return dfs(root.left,root.right) ;
    }

    private boolean dfs(TreeNode A, TreeNode B) {
     
        if(A==null && B==null) return true;
        if(A==null || B==null) return false;
        return A.val==B.val && dfs(A.left,B.right) && dfs(A.right,B.left);
    }
}

剑指 Offer 27. 二叉树的镜像

class Solution {
     
    public TreeNode mirrorTree(TreeNode root) {
     
        if(root==null) return root;

        TreeNode tmp = root.left;
        root.left = root.right;
        root.right = tmp;

        mirrorTree(root.left);
        mirrorTree(root.right);
        return root;
    }
}

leetcode-226. 翻转二叉树

class Solution {
     
    public TreeNode invertTree(TreeNode root) {
     
        if(root==null) return root;
        
        TreeNode tmp = root.left;
        root.left = root.right;
        root.right = tmp;
        
        invertTree(root.left);
        invertTree(root.right);
        return root;
    }
}

剑指 Offer 26. 树的子结构

class Solution {
     
    public boolean isSubStructure(TreeNode A, TreeNode B) {
     
        if(A==null || B==null) return false;
        return dfs(A,B) || isSubStructure(A.left,B) || isSubStructure(A.right,B);
    }

    private boolean dfs(TreeNode A, TreeNode B) {
     
        if(B==null) return true;
        if(A==null) return false;
        return A.val==B.val && dfs(A.left,B.left) && dfs(A.right,B.right);
    }
}

leetcode-572. 另一个树的子树

class Solution {
     
    public boolean isSubtree(TreeNode s, TreeNode t) {
     
        if(t==null) return true;
        if(s==null) return false;
       return dfs(s,t) || isSubtree(s.left,t) || isSubtree(s.right,t);
    }

    private boolean dfs(TreeNode s, TreeNode t) {
     
        if(s==null && t==null) return true;
        if(s==null || t==null) return false;
        return s.val==t.val && dfs(s.left,t.left) && dfs(s.right,t.right);
    }
}

你可能感兴趣的:(LeetCode)