浅谈算法题-三数之和

410 阅读4分钟

一、引言

在算法领域,“三数之和”是一个经典问题,它不仅考察了数据结构的应用,还体现了算法优化的重要性。本篇文章旨在深入剖析“三数之和”的解题思路,通过实例代码展示如何高效地找到数组中三个数的组合,使得它们的和等于给定的目标值,在这里目标值为0。

QQ_1720629392940.png

二、题目描述

假设你有一个整数数组 nums,任务是找出所有独特的三元组 (nums[i], nums[j], nums[k]),使得 i != j, i != k, j != k 并且 nums[i] + nums[j] + nums[k] == 0。返回所有这样的三元组。

QQ_1720629347339.png

三、解题思路

暴力解法

最直观的解法是使用三层循环遍历数组中的每一个可能的三元组,检查它们的和是否为0。这种解法的时间复杂度为 O(n^3),效率太低了。

排序 + 双指针

这道题我们可以采取“固定一个数,寻找另外两个”的策略。具体而言,我们遍历数组中的每一个元素,将其作为三元组中的第一个数。由于我们的目标是找到三数之和为零的组合,所以当三数之和大于零时,说明我取的数字大了,应该取小一点,当三数之和小于零时,说明我取的数字小了,应该取大一点。

以这个思路来想,首先我们要将数组排一下序,从小到大排序,这样便于我们重新找过数字,数字拿小了,往后一位拿,数字拿大了,拿前一位数字。

我们可以用左右两个指针来指向其他两个数,左指针指向最小的数(即遍历的数右边一位),右指针指向最大的数(即数组的最后一位),当三个数的和大于零,说明数字大了,右指针往左一位(左指针指向最小的数,他不能再取小了)当三个数的和小于零,说明数字小了,左指针往右一位(右指针指向最大的数,他不能再取大了),当三个数的和等于零,说明找到了一组,将这个组保存到结果数组中,然后左右指针分别往中间靠拢,直到左右指针重合,当左右指针重合,说明所有情况都检查过了,结束这一次循环

四、代码实现
var threeSum = function(nums) {
    nums.sort((a, b) => a - b); // 先对数组进行排序
        const results = [];
        const length = nums.length;
    
        for (let i = 0; i < length - 2; i++) {
            // 避免重复解,如果当前数字与前一个数字相同,则跳过
            if (i > 0 && nums[i] === nums[i - 1]) {
                continue;
            }
    
            let left = i + 1, right = length - 1; // 设置双指针
    
            while (left < right) {
                const sum = nums[i] + nums[left] + nums[right];
                if (sum < 0) {
                    left++; // 如果和小于零,移动左指针
                } else if (sum > 0) {
                    right--; // 如果和大于零,移动右指针
                } else {
                    // 找到一个解,将其添加到结果列表中
                    results.push([nums[i], nums[left], nums[right]]);
                    
                    // 移动指针并跳过重复的元素
                    while (left < right && nums[left] === nums[left + 1]) {
                        left++;
                    }
                    while (left < right && nums[right] === nums[right - 1]) {
                        right--;
                    }
                    
                    left++;
                    right--;
                }
            }
        }
    
        return results;
    };
五、代码结果

QQ_1720630104847.png

六、结语

通过本次探讨,我们深入了解了“三数之和”问题的算法解决方案。从最初的三重循环暴力搜索,到最终优化为结合排序与双指针技巧的高效算法,我们见证了算法设计中从繁复到精简的过程。这一转变不仅极大地提高了问题的解决效率,同时也彰显了算法优化在计算机科学中的重要价值。对“三数之和”问题的解决不仅是一次算法设计的实践,更是对计算机科学中优化理念的一次深刻领悟。它教会了我们如何在面对复杂问题时,通过合理的算法设计和技巧应用,化繁为简,达成既定目标。未来,在面对更多算法挑战时,我们应保持这份探索精神,勇于创新,不断优化,以期在计算机科学的广阔天地中,书写更加精彩的篇章。