算法篇——N个数之和大集合(js版)

1.两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。
链接:https://leetcode.cn/problems/two-sum

 

var twoSum = function(nums, target) {
    var indexList = [];
    var map = new Map();
    for(var i = 0; i < nums.length; i++) {
        // 遍历当前值时去找Map中可以得到目标值的加数
        var add = map.get(target - nums[i]);
        // 能找到就放入结果数组
        if(add != null) {
            indexList.push(add, i);
            return indexList;
        }
        // 否则将当前值放入map中
        map.set(nums[i], i);
    }
};
//2:0

15.三数之和

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

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

注意:答案中不可以包含重复的三元组。
链接:https://leetcode.cn/problems/3sum

var threeSum = function(nums) {
    var numList = [];
    var nList = nums.sort((a, b) => a - b);
    // 如果有序数组第一个元素大于0,则返回null
    if(nList[i] > 0) return numList;
    for(var i = 0; i < nList.length; i++) {
        var left = i + 1, right = nums.length - 1;
        // 去重
        if(nList[i] == nList[i - 1]) continue;
        while(left < right) {
            var sum = nList[left] + nList[i] + nList[right];
            // 说明三数之和大了,right向左移动
            if(sum > 0) right--;
            // 说明三数之和小了,left向右移动
            else if(sum < 0) left++;
            else {
                numList.push([nList[i], nList[left], nList[right]]);
                // 去重
                while(nList[left] == nList[left + 1]){
                    left++;
                }
                while(nList[right] == nList[right - 1]) {
                    right--;
                }
                left++
                right--;
            }
        }  
    }
    return numList;
};

18.四数之和

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。
链接:https://leetcode.cn/problems/4sum

var fourSum = function(nums, target) {
    var numList = [];
    var nList = nums.sort((a, b) => a - b);
    // 达不到四数之和的要求
    if(nums.length < 4) return numList;
    for(var i = 0; i < nList.length - 3; i++) {
        // 去重
        if(i > 0 && nList[i] == nList[i - 1]) continue;
        for(var j = i + 1; j < nList.length - 2; j++) {
            // 去重
            if(j > i + 1 && nList[j] == nList[j - 1]) continue;
            var left = j + 1, right = nList.length - 1;
            while(left < right) {
                var sum = nList[i] + nList[j] + nList[left] + nList[right];
                // 说明和大了,right向左移动
                if(sum > target) right--;
                // 说明和小了,left向右移动
                else if(sum < target) left++;
                else {
                    numList.push([nList[i], nList[j], nList[left], nList[right]]);
                    // 去重
                    while(nList[left] == nList[left + 1]){
                        left++;
                    }
                    while(nList[right] == nList[right - 1]) {
                        right--;
                    }
                    left++
                    right--;
                }
            }  
        }
    }
    return numList;
};

454.四数相加Ⅱ

给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
链接:https://leetcode.cn/problems/4sum-ii

var fourSumCount = function(nums1, nums2, nums3, nums4) {
    var map = new Map();
    var count = 0;
    // 前两个数组的求和遍历
    for(var i1 of nums1) {
        for(var i2 of nums2) {
            var sum = i1 + i2;
            // 和作为key,次数作为value
            map.set(sum, (map.get(sum) || 0) + 1)
        }
    }
    // 后两个数组的求和遍历
    for(var i3 of nums3) {
        for(var i4 of nums4) {
            var sum = i3 + i4;
            // 和作为key,次数作为value
            count += (map.get(-sum) || 0);
        }
    }
    return count;
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,我可以为你介绍一下分支限界法和装载问题的相关内容。 分支限界法是一种求解最优化问题的算法,通过不断扩展解空间,逐步缩小搜索范围,最终找到最优解。它的核心思想是将问题划分成许多子问题,并采用优先队列(或优先级队列)来维护待扩展的子问题集合,每次取出优先级最高的子问题进行扩展,直到找到最优解或者队列为空。 而装载问题是一种典型的分支限界法应用场景,它的主要思想是在给定的一些物品中选出尽可能多的物品放入容量为C的背包中,使得背包中物品的总重量不超过C,并且背包中物品的总价值最大。这个问题可以通过分支限界法来求解。 下面是一个简单的 Java 代码实现,用于解决装载问题: ```java import java.util.*; public class BranchAndBound { public static void main(String[] args) { int[] w = {5, 10, 20, 30}; // 物品的重量 int[] v = {50, 60, 140, 120}; // 物品的价值 int C = 50; // 背包的容量 int n = w.length; // 物品的数量 int[] x = new int[n]; // 记录每个物品是否被选中 PriorityQueue<Node> queue = new PriorityQueue<>(); queue.offer(new Node(-1, 0, 0)); // 将根节点加入队列中 while (!queue.isEmpty()) { Node node = queue.poll(); // 取出优先级最高的子问题 if (node.level == n - 1) { // 如果是叶子节点,更新最优解 for (int i = 0; i < n; i++) { x[i] = node.x[i]; } } else { int level = node.level + 1; int weight = node.weight; int value = node.value; if (weight + w[level] <= C) { // 左子节点表示选中当前物品 int[] left = Arrays.copyOf(node.x, n); left[level] = 1; queue.offer(new Node(level, weight + w[level], value + v[level], left)); } // 右子节点表示不选当前物品 queue.offer(new Node(level, weight, value, node.x)); } } int max = 0; for (int i = 0; i < n; i++) { if (x[i] == 1) { System.out.println("第" + (i + 1) + "个物品被选中"); max += v[i]; } } System.out.println("最大价值为:" + max); } // 子问题节点 static class Node implements Comparable<Node> { int level; // 当前节点所在的层级 int weight; // 当前节点的背包重量 int value; // 当前节点的背包价值 int[] x; // 记录每个物品是否被选中 public Node(int level, int weight, int value) { this.level = level; this.weight = weight; this.value = value; this.x = new int[0]; } public Node(int level, int weight, int value, int[] x) { this.level = level; this.weight = weight; this.value = value; this.x = x; } @Override public int compareTo(Node o) { return o.value - this.value; // 根据价值进行优先级比较 } } } ``` 希望这个简单的例子能帮助你更好地理解分支限界法和装载问题。如果你还有其他问题或者疑惑,欢迎随时向我提出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

低保和光头哪个先来

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值