给定一个数组,数组中任意数量1-9的数,可以组合成10的方案有多少个

博客围绕从给定数组中选取任意个数使其和为给定值的问题展开。介绍了JS和Java的写法,还提及leetcode相关题目,如从有序数组可重复选取、从无序数组不可重复选取的情况,解题思路主要是回溯法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以下只是用我自己理解的方法解决的,有更优雅的方法可以留言,我也可以学习下。

JS写法

/**
 *  给定一个数组,数组中任意数量1-9的数,可以组合成10的方案有多少个
 */
const test1 = [1, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 8, 9]
const resMap = []
const counter = arrEleCounter(test1)
peer(counter, 10, '')
const removeDuplicateResult = resMap.map(allItem => allItem.split('+').map(removeDuplicateItem => Number(removeDuplicateItem)).sort().join('+'))
/*以+为分割符,然后Number化,然后排序,再转为string*/
const mySet = new Set(removeDuplicateResult)

console.log('各个数字出现的个数:', counter)
console.log('大于5的只显示一次')
console.log('未去重结果详情:', resMap)
console.log('未去重结果个数:', resMap.length)
console.log('去重之后的结果详情:', mySet)
console.log('去重之后的结果个数:', mySet.size)
//深拷贝
function deepCopy(o) {
  if (o instanceof Array) { // 先判断Array
    var n = []
    for (var i = 0; i < o.length; ++i) {
      n[i] = deepCopy(o[i])
    }
    return n
  } else if (o instanceof Object) {
    var n = {}
    for (var i in o) {
      n[i] = deepCopy(o[i])
    }
    return n
  } else {
    return o
  }
}
// 统计每个数字出现的次数
function arrEleCounter(arr) {
  var b = {}
  for (let i = 0; i < arr.length; i++) {
    b[arr[i]] = (b[arr[i]] + 1) || 1
    // 大于5的数 个数已经没有意义了
    if (arr[i] > 5) {
      b[arr[i]] = 1
    }
  }
  return b
}
// 递归分解
function peer(obj, num, str) {
  for (const item in obj) {
    const item_num = Number(item)// string转为number
    if (item_num < (num + 1) / 2) {
      for (let i = 1; i < obj[item] + 1; i++) {
        const diff = num - item_num * i
        if (diff <= 0) {
          return false
        }
        const restObj = deepCopy(obj)
        restObj[item] = restObj[item] - i
        if (restObj[item] === 0) {
          delete restObj[item]
        }
        const obj_keys = Object.keys(restObj)
        if (obj_keys.includes(diff.toString())) {
          const compression = `${str}${item}+${diff}`
          if (eval(compression) === 10) {
            if (compression.substr(0, 1) > 1 && compression.substr(2, 1) < 5) {
              return false
            }
            resMap.push(compression)
            peer(restObj, diff, `${str}${item}+`)
          }
        } else {
          delete restObj[item]
          peer(restObj, diff, `${str}${item}+`)
        }
      }
    }
  }
}

运行结果

去重之后的结果详情: Set { '1+9',
  '1+1+8',
  '1+1+1+2+5',
  '1+1+1+2+2+3',
  '1+1+1+3+4',
  '1+1+2+6',
  '1+1+1+1+2+4',
  '1+1+2+2+4',
  '1+1+3+5',
  '1+2+3+4',
  '1+3+6',
  '1+4+5',
  '2+8',
  '4+6',
  '5+5' }
去重之后的结果个数: 15

更优雅的写法

java

常见算法 - 从给定数组中选取任意个数(可重复),使其和为给定值。

从给定有序数组中选取任意个数(可重复),使其和为给定值(leetcode39):

思路:回溯法的练习题。因为可以重复,注意递归调用时可以从当前位置开始取。。

从给定无序数组中选取任意个数(不可重复),使其和为给定值(leetcode40):

思路:回溯法的练习题,按照上题思路,可以先将数组排序,不同点是因为不可以重复,递归调用要从当前位置的下一个数开始取。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值