JavaScript-算法-(二三四)数之和

(二三四)数之和

两数之和

1. 问题描述
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum。

2. 解题思路

  1. num1+num2=target,将num2转化为target-num1
  2. 定义一个空数组arrNum[],以nums[i]的值为下标,以nums[i]的下标为值
  3. 循环遍历
  4. 当num2在arrNum[]中不存在,则将nums的数组下标存进arrNum中,若存在,说明找到了符合两数之和的num2,返回结果
    var twoSum = function(nums, target) {
    var arrNum = {};//存储出现过的数组元素
    for(var i = 0; i < nums.length; i++){
        var otherNum = target - nums[i];//目标值-当前遍历值得到另一个整数
        var otherNumIndex = arrNum[otherNum]//另一个整数的下标
        if(otherNumIndex != undefined && otherNumIndex != i){
            return arrNum = [otherNumIndex,i];
        }
        else{
            arrNum[nums[i]] = i;
        }
    }

};

3. 图解

target99999
i01234
num[i]23487
otherNum=target-num[i]76512
otherNumIndexarrNum[7]arrNum[6]arrNum[5]arrNum[1]arrNum[2]
otherNumIndex在arrNum中存在否xxxx
j=num[i]2
arrNum[j]0
j=num[i]3
arrNum[j]1
j=num[i]4
arrNum[j]2
j=num[i]8
arrNum[j]3
otherNumIndex0
i4

两数之和(输入有序数组)

1. 问题描述
给定一个已按照 升序排列 的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。
函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length 。
你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted

2.解题思路一

  1. 定义一个空数组,存储下标值
  2. 左右指针,循环遍历
  3. 左指针指向的值+右指针指向的值=target,返回左右指针,根据题意,需要进行+1处理。因为数组下标是从0开始的
  4. 若和大于目标值,左指针右移
  5. 若和小于目标值,右指针左移
    var twoSum = function(numbers, target) {
    var arrNum = [];
    var len = numbers.length;
    var left = 0;
    var right = len - 1;
    while(left < right){
        if(numbers[left] + numbers[right] == target){
            return arrNum = [left + 1, right + 1];
        }
        else if(numbers[left] + numbers[right] > target) right--;
        else if(numbers[left] + numbers[right] < target) left++;
    }
    return arrNum;
};

3. 图解一
输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。

下标0123
nums271115执行
leftrightnums[left]+nums[right]>target,right–
leftrightnums[left]+nums[right]>target,right–
leftrightnums[left]+nums[right]=target,return [left+1,right+1]

4. 解题思路二

  1. 使用哈希表记录目标值的下标
  2. for循环遍历
    var twoSum = function(numbers, target) {
    let num = new Map();
    for(let i = 0; i < numbers.length; i++){
        let otherNum = target - numbers[i];
        if(num.has(otherNum)) return [num.get(otherNum), i + 1];
        num.set(numbers[i], i + 1);
    }

};

5. 图解二
输入:numbers = [2,4,7,11,15], target = 9
输出:[1,3]

itargetnumbers[i]otherNumnum执行setreturn
0927[]otherNum在num中不存在,将该值存进numnum=[2,1]
1945[2,1]otherNum在num中不存在,将该值和遍历值i存进numnum=[[2,1],[4,2]]
2972[[2,1],[4,2]]otherNum在num中存在,返回该值在num中的下标和当前遍历值i+1[1,3]

三数之和

1. 问题描述
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum

2.解题思路

  1. 对数组nums从小到大进行排序
  2. for循环+双指针
    var threeSum = function(nums) {
    let arrNum = [];
    if(nums == null || nums.length < 3) return arrNum;
    nums.sort((a, b) => a - b); // 排序
    //以排头为初始值,并取左右两端的值
    for(var i = 0; i < nums.length - 2; i++){
        var left = i + 1;
        var right = nums.length - 1;
        if(nums[i] > 0) break; //取到大于0的值,说明三数之和一定大于0
        if(i > 0 && nums[i] == nums[i - 1]) continue;//取值重复
        while(left < right){
            if(nums[i] + nums[left] + nums[right] == 0){
                arrNum.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--;
            }
            else if(nums[i] + nums[left] + nums[right] > 0) right--;
            else if(nums[i] + nums[left] + nums[right] < 0) left++;
        }
        
    }
    return arrNum;

};

3.图解
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]

nums-1012-1-4
排序后-4-1-1012
轮数-4-1-1012执行
1ileftrighti+left+right<0,left++
1ileftrighti+left+right<0,left++
1ileftrighti+left+right<0,left++
1ileftrighti+left+right<0,left++
1ileft/righti++
2ileftrighti+left+right=0,left++,right–,[-1,-1,2]
2ileftrighti+left+right=0,left++,right–,[-1,0,1]
2irightlefti++
3ileftrightnum[i]=num[i-1],i++
4ileftrighti+left+right>0,right–
4ileft/rightreturn arrNum

最接近的三数之和

1. 问题描述
给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum-closest

2. 解题思路

  1. 将数组升序排列
  2. for循环+双指针
  3. 类似于三数之和,只是每轮需要判断三数之和与目标值的差值的绝对值是否最小。
    var threeSumClosest = function(nums, target) {
    var arrNum = [];
    if(nums == null || nums.length < 3) return arrNum;
    var min = Number.MAX_VALUE;
    var result = Number.MAX_VALUE;
    nums.sort((a, b) => (a - b));
    for(var i = 0; i < nums.length - 2; i++){
        var left = i + 1;
        var right = nums.length - 1;
        while(left < right){
            var sum = nums[i] + nums[left] + nums[right];
            if(Math.abs(target - sum) < min){
                min = Math.abs(target - sum);
                result = sum;
            }
            if(sum == target) return target;//与目标值相同,直接返回
            else if(sum > target) right--;
            else if(sum < target) left++;

        }
       
    }
    return result;

};

四数之和

1. 问题描述
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
注意:答案中不可以包含重复的四元组。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/4sum

2.解题思路

  1. 对数组进行排序
  2. 双重for循环 + 双指针
    var fourSum = function(nums, target) {
    var arrNum = [];
    var len = nums.length;
    nums.sort((a, b) => a - b);
    if(nums == null || len < 4) return arrNum;
    for(var i = 0; i < len - 3; i++){
        if(nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) break;
        if(nums[i] + nums[len - 1] + nums[len - 2] + nums[len - 3] < target) continue;
        if(i > 0 && nums[i] == nums[i - 1]) continue;
        for(var j = i + 1; j < len - 2; j++){
            if(j > i + 1 && nums[j] == nums[j - 1]) continue;
            if(nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) break;
            if(nums[i] + nums[j] + nums[len - 1] + nums[len - 2] < target) continue;
            var left = j + 1;
            var right = len - 1;
            while(left < right){
               //找到目标四元组
               if(nums[i] + nums[j] + nums[left] + nums[right] == target){
                   arrNum.push([nums[i], nums[j], nums[left], nums[right]]);
                   while(left < right && nums[left] == nums[left + 1]) left++;
                   while(left < right && nums[right] == nums[right - 1]) right--;
                   left++;
                   right--;
               }
               //四元组比目标值小,左移
               else if(nums[i] + nums[j] + nums[left] + nums[right] < target) left++;
               //四元组比目标值大,右移
               else if(nums[i] + nums[j] + nums[left] + nums[right] > target) right--;
           }
        }
    }
    return arrNum;
};

3.图解
输入:nums = [-1,0,-1,0,-2,2], target = 0
输出:[[-2,0,0,2],[-1,-1,0,2]]

nums-10-10-22
排序后-2-1-1002
轮数(ij)-2-1-1002执行
11ijleftrighti+j+left+right<0,left++
11ijleftrighti+left+right<0,left++
11ijleftrightnum[left]==num[left+1],left++
11ijleft/rightj++
12ijleftrighti+j+left+right<0,left++
12ijleftrightnum[left]==num[left+1],left++
12ijleft/rightj++
12ijleftrighti+j+left+right=0,left++,right–,[-2.0,0,2]
12ijrightlefti++
21ijleftrighti+j+left+right=0,left++,right–,[-1.-1,0,2]
21ijleft/rightj++
22ijleftrighti+j+left+right>0,right–
22ijleft/righti++
31ijleftrightnum[i]=num[i-1],i++
31ijleftrightreturn arrNum
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值