Files
logseq-1/journals/2023_09_30.md
2024-06-17 22:24:52 +08:00

4.5 KiB
Raw Permalink Blame History

  • 二叉树的遍历 #算法
  • 排序算法 #算法
  • 三数之和 #算法
    • 15. 三数之和 - 力扣LeetCode collapsed:: true
      • //给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != 
        //k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请 
        //
        // 你返回所有和为 0 且不重复的三元组。 
        //
        // 注意:答案中不可以包含重复的三元组。 
        //
        // 
        //
        // 
        //
        // 示例 1 
        //
        // 
        //输入nums = [-1,0,1,2,-1,-4]
        //输出:[[-1,-1,2],[-1,0,1]]
        //解释:
        //nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
        //nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
        //nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
        //不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
        //注意,输出的顺序和三元组的顺序并不重要。
        // 
        //
        // 示例 2 
        //
        // 
        //输入nums = [0,1,1]
        //输出:[]
        //解释:唯一可能的三元组和不为 0 。
        // 
        //
        // 示例 3 
        //
        // 
        //输入nums = [0,0,0]
        //输出:[[0,0,0]]
        //解释:唯一可能的三元组和为 0 。
        // 
        //
        // 
        //
        // 提示: 
        //
        // 
        // 3 <= nums.length <= 3000 
        // -10⁵ <= nums[i] <= 10⁵ 
        // 
        //
        // Related Topics 数组 双指针 排序 👍 6404 👎 0
        
        
        import java.sql.Array;
        import java.util.ArrayList;
        import java.util.Arrays;
        
        //leetcode submit region begin(Prohibit modification and deletion)
        class Solution {
            public List<List<Integer>> threeSum(int[] nums) {
                List<List<Integer>> result = new ArrayList<List<Integer>>();
                int n = nums.length;
                Arrays.sort(nums);
                for (int first = 0; first < n -2; ++first) {
                    // 如果a的值与上一轮一样就跳过
                    if(first != 0 && nums[first] == nums[first - 1]) {
                        continue;
                    }
                    if (nums[first] + nums[first + 1] + nums[first + 2] > 0) {
                        break;
                    }
                    if (nums[first] + nums[n-1] +nums[n-2] < 0) {
                        continue;
                    }
                    //c为nums末端值
                    int third = n -1;
                    int target = -nums[first];
                    for (int second = first + 1; second < n -1; ++second) {
                        // 如果b的值和上一轮相同跳过
                        if(second > first + 1 && nums[second] == nums[second - 1]) {
                            continue;
                        }
                        // 固定a和b移动c且保证c>a
                        while(second < third && nums[third] + nums[second] > target) {
                            --third;
                        }
                        // 如果b和c重合终止b的循环
                        if(second == third) {
                            break;
                        }
                        if (nums[third] + nums[second] == target){
                            result.add(Arrays.asList(nums[first], nums[second], nums[third]));
                        }
                    }
                }
                return result;
            }
        }
        //leetcode submit region end(Prohibit modification and deletion)
        
        
    • 排序+双指针
      • 注意值的变化两个for循环都是使用++first及++second
      • 第二个值从first+1开始变化
      • 第三个值初始为n-1使用while来进行自减即--third需要判断三个值是否大于0且second要小于third
    • 优化
      • 因为已经排序可以判断连续的三个是否大于0大于0可以不用再找了
      • 可以判断a与末尾的两个数是否小于0小于0可以跳过此轮b循环
      • 注意a的值要取n-2b取n-1否则会发生下标越界