LeetCode 15 – 三数之和

题目描述

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] = 0 。请你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

题目分析

哈希表+去重

遍历一次数组,将所有数字放入哈希表,同时记录每个数字的数量
枚举下标 i 和 j,判断哈希表中是否存在数字值为-num[i]-num[j],且要保证和哈希表记录的数字数量不冲突,存在则放入结果集合中。结果集合要做去重。
时间复杂度O(n^2)

排序+双指针(推荐)

将数组从小到大排序。
枚举下标 i,枚举时要判断是否和 i – 1 重复
将 j 初始化为 i+1,k 初始化为 nums.length - 1
判断三个数字之和 sum:
– 大于0: k 向左移动一位
– 小于0: j 向右移动一位
– 等于0: 放入结果集合中。j++k-- 都可以,但要保证和调整前的数字不重复

为什么 j 和 k 只能向内侧移动?
思考时要从初始状态思考,而不是直接从中间态思考。
对于初始状态,j 在左边界,k 在右边界。以 sum > 0 为例,对于 k 来说,j 已经是当前数组的最小值,因此无论后续 j 移动到哪里,sum 都会变得更大,此刻 k 对应的数字是无用的,所以可以将它删除。删除后的新数组,j 和 k 依然是左边界和右边界。代码里没必要真的删除,而是限制指针只能向内侧移动。
时间复杂度O(n^2)

Java

public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        Arrays.sort(nums);
        for (int i = 0; i < nums.length; i++) {
            int j = i + 1;
            int k = nums.length - 1;
            if (nums[i] > 0) {
                break;
            }
            if (i > 0 && nums[i] == nums[i - 1]) {
                continue;
            }
            while (j < k) {
                int sum = nums[i] + nums[j] + nums[k];
                if (sum == 0) {
                    result.add(Arrays.asList(nums[i], nums[j], nums[k]));
                    int p = nums[j];
                    while (j < k && nums[j] == p) {
                        j++;
                    }
                } else if (sum > 0) {
                    k--;
                } else {
                    j++;
                }
            }
        }
        return result;
    }

Kotlin

fun threeSum(nums: IntArray): List<List<Int>> {
        val result = ArrayList<List<Int>>()
        nums.sort()
        for (i in nums.indices) {
            var j = i + 1
            var k = nums.size - 1
            if (i > 0 && nums[i] == nums[i - 1]) {
                continue
            }
            if (nums[i] > 0) {
                break
            }

            while (j < k) {
                val sum = nums[i] + nums[j] + nums[k]
                if (sum == 0) {
                    result.add(arrayListOf(nums[i], nums[j], nums[k]))
                    val p = nums[j]
                    while (j < k && nums[j] == p) {
                        j++
                    }
                } else if (sum > 0) {
                    k--
                } else {
                    j++
                }
            }
        }
        return result
    }

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部