该浏览器不支持canvas

leetcode新年病房暴乱康复计划 15. 三数之和 16. 最接近的三数之和 18. 四数之和 JS解法

//15
var
threeSum = function(nums) { var ans = []; var nums = nums.sort(function(a,b){return a - b}); var flag = 0; while(flag < nums.length - 2){ if (nums[flag] > 0){ break; } var l = flag + 1,r= nums.length - 1; while(l < r){ var res = nums[flag] + nums[l] + nums[r]; if(res === 0){ ans.push(new Array(nums[flag], nums[l], nums[r])); while(++l < r && nums[l - 1] === nums[l]){} while(l < --r && nums[r + 1] === nums[r]){} }else if(res < 0){ while(++l < r && nums[l - 1] === nums[l]){} }else{ while(l < --r && nums[r + 1] === nums[r]){} } } while(++flag < nums.length - 2 && nums[flag] === nums[flag - 1]){} } return ans; };

从第一个开始指定一个标尺,然后设置L=标尺+1,R=END双指针法贪心往内部推进 15题的关键是排序后最左侧为正数的优化 节约大量运行时间

//16
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var threeSumClosest = function(nums, target) {
    var ans = -99999999;
    var len = nums.length;
    nums.sort((a, b) => {return a - b;});
    for(var i = 0; i < len - 2; i++){
        var l = i + 1, r = len - 1;
        while(l < r){
            var sum = nums[i] + nums[l] + nums[r];
            if(Math.abs(ans - target) > Math.abs(sum - target)){
                ans = sum;
            }
            sum = sum - target;
            if(sum < 0){
                while(l < r && nums[l] === nums[++l]){}
            }else if(sum > 0){
                while(l < r && nums[r] === nums[--r]){}
            }else{
                break;
            }
        }
        if(ans === target) break;
    }
    return ans;
};

16题就老老实实比吧 因为要凑数所以不能采取上题的优化

//18
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[][]}
 */
var fourSum = function(nums, target) {
    var ans = [];
    var len = nums.length;
    nums.sort((a,b) => {return a - b});
    for(var i = 0; i < len - 3; i++){
        if(i > 0 && nums[i - 1] === nums[i]) continue;
        for(var j = i + 1; j < len - 2; j++){
            if(j > i + 1 && nums[j - 1] === nums[j]) continue;
            var l = j + 1, r = len - 1;
            while(l < r){
                var sum = nums[i] + nums[j] + nums[l] + nums[r];
                if(sum < target){
                    while(l < r && nums[l] === nums[++l]){}
                }else if(sum > target){
                    while(l < r && nums[r] === nums[--r]){}
                }else{
                    ans.push([nums[i], nums[j], nums[l], nums[r]]);
                    while(l < r && nums[l] === nums[++l]){}
                    while(l < r && nums[r] === nums[--r]){}
                }
            }
        }
    }
    return ans;
};

18这题相当于给16套了个壳 指定第一个为原来三数之和的标尺后 再把后面的按三数之和走一遍

posted @ 2020-01-29 22:47  真是啰嗦  阅读(208)  评论(0)    收藏  举报