数字的魔力:探索三数之和,引爆你的逻辑思维!

121 阅读4分钟

问题:三数之和

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

思路

标签:数组遍历

  • 首先对数组进行排序,排序后固定一个数 nums,再使用左右指针指向 nums[i]后面的两端,数字分别为 nums[L] 和 nums[R],计算三个数的和 sumsumsum 判断是否满足为 000,满足则添加进结果集。
  • 如果 nums[i]大于 000,则三数之和必然无法等于 000,结束循环
  • 如果 nums[i] == nums[i−1],则说明该数字重复,会导致结果重复,所以应该跳过。
  • 当 sum == 0 时,nums[L] == nums[L+1] 则会导致结果重复,应该跳过,L++
  • 当 sum== 000 时,nums[R] == nums[R−1] 则会导致结果重复,应该跳过,R−−R--R−− 时间复杂度:O(n^2) ,n为数组长。

运行代码:

var threeSum = function(nums) {
    let box =[]
    const length = nums.length
    if (length<3 || nums == null) return box;
    nums.sort((a,b) => a-b);//升序排序
    for (let i = 0;i < length; i++) {
        if (nums[i] > 0) break;
        //如果首位数字大于0,那么这个数组内无论哪三个相加都不可能为0,所以结束循环
        if(i > 0 && nums[i] == nums[i-1]) continue; //去重
        let L = i+1;
        let R = length-1;
        while(L < R){
            const sum = nums[i] + nums[L] + nums[R];
            if(sum == 0){
                box.push([nums[i],nums[L],nums[R]]);
                while (L<R && nums[L] == nums[L+1]) L++; //去重
                while (L<R && nums[R] == nums[R-1]) R--;//去重
                L++;
                R--;
            }
            else if (sum < 0) L++;
            else if (sum > 0) R--;
        }
    }        
    return box;
}
  • 首先,声明一个空数组 ans 来保存符合条件的三元组。同时,获取输入数组的长度,并进行判断,如果数组为空或长度小于3,则直接返回空数组 ans
  • 对输入数组 nums 进行排序,通过使用 nums.sort((a, b) => a - b),将数组按照升序进行排序。
  • 接下来,使用一个循环遍历数组中的每个数字,作为三元组的第一个数。设当前数字的索引为 i
  • 在循环体内部,首先进行一个判断,如果当前数字大于0,则三数之和一定大于0,因此可以直接跳出循环。
  • 接着,使用另一个判断去重,如果 i 大于0,并且当前数字与前一个数字相等,说明这两个数字已经被考虑过了,为了避免重复,我们直接进入下一次循环,即 continue
  • 定义两个指针 LR,分别指向当前数字的下一个位置和数组的最后一个位置。
  • 进入一个 while 循环,循环条件是 L < R
  • 在循环体内部,计算当前三个数的和 sum = nums[i] + nums[L] + nums[R]
  • 如果 sum 等于0,说明找到了满足条件的三元组,将这个三元组 [nums[i], nums[L], nums[R]] 加入到结果数组 ans 中。
  • 随后,进行去重操作。首先,将指针 L 向右移动一位,直到找到一个与当前数字不相等的数为止。然后,将指针 R 向左移动一位,同样直到找到一个与当前数字不相等的数为止。
  • 最后,将指针 LR 分别向右和向左移动一位,继续寻找下一个满足条件的三元组。
  • 当循环结束后,返回结果数组 ans

总结

三数之和问题是算法领域中一个重要且经典的问题,它在很多实际应用中都有广泛的应用。 在实际应用中,我们需要根据具体的需求和数据规模选择合适的解决方案。双指针法和哈希表法在时间复杂度上较为接近,但在空间复杂度和结果的完整性上存在差异。优化的双指针法则可以在一定程度上提高效率,但仍然无法找到所有的组合。 除了以上提到的解决方案,还有其他的算法思路可以尝试,如回溯算法等。每种方法都有其特点和适用范围,需要根据具体情况进行选择。 在解决三数之和问题时,我们还需要考虑一些特殊情况,如数组中存在重复元素、有序数组和无序数组等。这些因素可能会对选择解决方案和优化算法产生影响,我们需要根据实际情况进行相应的调整和考虑。 总之,三数之和问题是一个具有挑战性的问题,通过选择合适的解决方案和优化算法,我们可以在较短的时间内找到满足条件的三元组。希望本文能够对读者理解和解决三数之和问题提供一些参考和指导,同时也能激发更多关于算法设计和优化的思考。