JavaScript实现从数组中选出和等于固定值的n个数

yizhihongxing

下面是JavaScript实现从数组中选出和等于固定值的n个数的完整攻略:

问题描述

假设有一个数组arr和一个固定值target,如何从arr中选出n个数,使得这n个数的和等于target。

解决方案

1. 暴力破解

最简单粗暴的方法当然是暴力破解,即枚举所有的 n 个数的组合情况,计算它们的和,如果等于 target,则返回这个组合。但其时间复杂度为O($\binom{n}{len(arr)}$),不太适合大规模数据。示例代码:

function findNNumbers(arr, target, n) {
  const getAllCombs = (arr, n) => {
    if (n === 1) {
      return arr.map(item => [item]);
    }
    let allCombs = [];
    for (let i = 0; i < arr.length - n + 1; i++) {
      const comb = getAllCombs(arr.slice(i + 1), n - 1).map(item => [arr[i], ...item]);
      allCombs = [...allCombs, ...comb];
    }
    return allCombs;
  };
  const combs = getAllCombs(arr, n);
  return combs.find(comb => comb.reduce((a, b) => a + b, 0) === target);
}

const arr = [1, 3, 5, 7];
const target = 10;
const n = 2;
console.log(findNNumbers(arr, target, n)); // [3,7]

2. 动态规划

在暴力破解的基础上进行优化,可以采用动态规划的思想。定义 dp[i][j][k] 表示前i个数中选j个数的和是否等于k,若dp[i][j][k]为true,则表示存在一组数的和等于k。则有以下状态转移方程:

  • dp[i][j][k] = dp[i-1][j][k] // 不选第i个数
  • dp[i][j][k] = dp[i-1][j-1][k-arr[i]] // 选第i个数

时间复杂度为$O(ntargetlen(arr))$,可以通过本题。示例代码:

function findNNumbers(arr, target, n) {
  const results = [];
  const dp = Array.from({ length: arr.length + 1 }, () => Array.from({ length: n + 1 }, () => Array.from({ length: target + 1 }, () => false)));
  for (let i = 1; i <= arr.length; i++) {
    for (let j = 1; j <= Math.min(i, n); j++) {
      for (let k = 1; k <= target; k++) {
        dp[i][j][k] = dp[i - 1][j][k];
        if (arr[i - 1] === k && j === 1) {
            dp[i][j][k] = true;
        }
        if (arr[i - 1] < k && j > 1) {
            dp[i][j][k] = dp[i - 1][j - 1][k - arr[i - 1]];
        }
        if (dp[i][j][k] && j === n && k === target) {
            const result = [];
            let x = i, y = j, z = k;
            while (x > 0 && y > 0 && z > 0) {
              if (dp[x][y][z]) {
                result.unshift(arr[x - 1]);
                y--;
                z -= arr[x - 1];
              }
              x--;
            }
            results.push(result);
        }
      }
    }
  }
  return results;
}

const arr = [1, 3, 5, 7, 9];
const target = 10;
const n = 3;
console.log(findNNumbers(arr, target, n)); // [ [3, 5, 2], [7, 2, 1] ]

这里假设找到所有可能的组合,如果只要其中任意一种,则可以在 dp 中用一个boolean变量标识是否找到即可。

3. 回溯法

利用回溯法可以找到所有符合条件的组合,而不仅是其中任意一种。示例代码:

function findNNumbers(arr, target, n) {
  const results = [];
  const dfs = (startIndex, path, sum) => {
    if (path.length === n && sum === target) {
      results.push([...path]);
      return;
    }
    for (let i = startIndex; i < arr.length && sum + arr[i] <= target && path.length + arr.length - i >= n; i++) {
      path.push(arr[i]);
      dfs(i + 1, path, sum + arr[i]);
      path.pop();
    }
  }
  dfs(0, [], 0);
  return results;
}

const arr = [1, 3, 5, 7, 9];
const target = 10;
const n = 3;
console.log(findNNumbers(arr, target, n)); // [ [1, 5, 4], [1, 3, 6], [1, 9, 0], [3, 5, 2], [7, 2, 1] ]

其中,startIndex 表示每一轮开始枚举的起点,path 是当前已选的数列,sum 表示当前已选的数列的和。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript实现从数组中选出和等于固定值的n个数 - Python技术站

(0)
上一篇 2023年6月25日
下一篇 2023年6月25日

相关文章

  • Jmeter如何基于命令行运行jmx脚本

    要基于命令行运行JMeter的JMX脚本,需要使用以下步骤: 进入JMeter的bin目录:cd apache-jmeter-x.x.x/bin/(这里的x.x.x代表的是JMeter的版本号) 使用以下命令运行JMX脚本:./jmeter -n -t [testplan.jmx] -l [testresult.jtl]其中,[testplan.jmx]是需…

    other 2023年6月26日
    00
  • .net反编译的九款神器

    .NET反编译是一种将已编译的.NET程序集转换回其源代码的过程。这种技术可以帮助开发人员理解和修改现有的.NET程序集。以下是.NET编译的九款神器的完整攻略: dnSpy dnSpy是一免费的.NET反编译器,可以反编译.NET程序集并查看其源代码。它还支持调试反编译的代码,并提供了一些其他有用的功能,如查看程序集的元数据和IL代码。以下是使用dnSpy…

    other 2023年5月7日
    00
  • Nginx配置之location的匹配优先级浅析

    Nginx配置之location的匹配优先级浅析 1. 什么是Nginx的location指令 在Nginx的配置文件中,location指令用于匹配URL,并指定相应的处理方式。我们可以根据location指令来配置Nginx对特定URL的处理方式,包括转发请求到后端服务器、返回固定内容等。 2. location的匹配优先级 Nginx的location…

    other 2023年6月28日
    00
  • Android自定义选项卡切换效果

    下面我来详细讲解“Android自定义选项卡切换效果”的完整攻略。这个过程可以分为以下几个步骤: 步骤一:创建一个TabLayout 首先需要在布局文件中创建一个TabLayout,它是用来放置选项卡的。可以选择使用系统自带的TabLayout,也可以使用第三方库。以下是一个使用系统自带的TabLayout的示例: <com.google.androi…

    other 2023年6月25日
    00
  • C语言中的运算符优先级和结合性一览表

    C语言中的运算符优先级和结合性一览表 运算符优先级和结合性非常重要,它们决定了表达式中运算符的执行顺序。在C语言中,运算符的优先级和结合性是根据一定的规则确定的。 以下是C语言中常见运算符的优先级和结合性一览表: 优先级 运算符 描述 结合性 1 ++ — 后缀自增,后缀自减 左到右 () [] . -> 函数调用,数组下标,成员访问 (类型) 强制…

    other 2023年6月28日
    00
  • Java编程中利用InetAddress类确定特殊IP地址的方法

    Java编程中利用InetAddress类确定特殊IP地址的方法 在Java编程中,可以使用InetAddress类来确定特殊IP地址。InetAddress类提供了一些方法来获取和操作IP地址。下面是一个详细的攻略,包含了两个示例说明。 步骤1:导入必要的类 首先,我们需要导入java.net包中的InetAddress类。可以使用以下代码导入: impo…

    other 2023年7月30日
    00
  • Android基于OpenGL的GLSurfaceView创建一个Activity实现方法

    下面是详细讲解“Android基于OpenGL的GLSurfaceView创建一个Activity实现方法”的完整攻略。 前置知识 在学习本攻略前,建议您已经具备以下知识: Android基础知识、Java编程基础知识; 熟悉Android编程中Activity、View的相关知识; OpenGL ES的基本概念和使用方法。 创建GLSurfaceView …

    other 2023年6月27日
    00
  • Vue Router嵌套路由(children)的用法小结

    Vue Router嵌套路由(children)的用法小结 Vue Router是Vue.js官方的路由管理器,它允许我们在Vue应用中实现页面之间的导航和路由功能。其中,嵌套路由(children)是Vue Router提供的一个强大功能,它允许我们在一个路由下定义子路由,从而实现更复杂的页面结构和导航。 嵌套路由的基本用法 要使用嵌套路由,我们需要在Vu…

    other 2023年7月28日
    00
合作推广
合作推广
分享本页
返回顶部