编程笔记:给出一个正整数,求解满足上面公式的所有算式组合

朋友丢了一道题目过来,手痒就解决了一下。
测试数据尽量不要超过25,否则要等很久甚至卡死。
这种题应该有公式之类的可以计算,以下2个方法纯粹是练手而已

题目描述

给定一个正整数,我们可以定义出下面的公式:
N=a[1]+a[2]+a[3]+…+a[m];
a[i]>0,1<=m<=N;
对于一个正整数,求解满足上面公式的所有算式组合,如,对于整数 4 :
4= 4;
4 = 3 + 1;
4 = 2 + 2;
4 = 2 + 1 + 1;
4 = 1 + 1 + 1 + 1;
所以上面的结果是 5 。
注意:对于 “4 = 3 + 1” 和 “4 = 1 + 3”,这两处算式实际上是同一个组合!
输入
4
10
20
输出
5
42
627
解答要求:时间限制:1000ms, 内存限制:64MB

解答方法1(效率低一些)
const res = [];
function calculate(n,prev,init){
	if(n > 1){
		for(let i=1; i<=n/2; i++){
			const arr = [].concat(prev);
			if(n-i > 1){
				const newArr = arr.concat(i,n-i);
				let str = newArr.sort().join('+');
				if(res.indexOf(str) < 0){
					let sum = newArr.reduce((a,b) => a+b);
					if(sum === init){
						res.push(str);
					}
				}
				if(arr.length){
					for(let k=0; k<arr.length; k++){
						if(i <= arr[k]){
							arr.splice(k, 0, i);
							break;
						}
					}
				}else{
					arr.push(i);
				}
				calculate(n-i, arr, init);
			}
		}
	}
}
function getAll(num){
	calculate(num, [], num);
	//如果num > 1,则最后数量要加多2个不参与calculate计算的,一个是num = num,一个是num = 1 + 1 + ... + 1
	const sum = num > 1 ? res.length + 2 : 1;
	console.log('参与计算的数字:' + num + ',总数:'+sum);
	console.log('计算所得算式:',res);
}
console.time('共用时间:');
getAll(20);
console.timeEnd('共用时间:');
  • 执行结果,如下图
    执行结果:
解答方法2(效率高一些)
const res = new Set();
function calculate(n,prev,init){
	if(n > 1){
		for(let i=1; i<=n/2; i++){
			const arr = [].concat(prev);
			const left = n - i;
			if(left > 1){
				let str = '';
				let count = 0;
				let sum = 0;
				arr.forEach((sv,si) => {
					if(count < 1 && i <= sv){
						str += i + '+';
						sum += sv;
						count ++;
					}else	if(count < 2 && left <= sv){
						str += left + '+';
						sum += sv;
						count ++;
					}
					str += sv + '+';
					sum += sv;
				})
				if(count === 0){
					str += i + '+' + left + '+';
					sum += i + left;
				}else if(count === 1){
					str += left + '+';
					sum += left;
				}
				str = str ? str.slice(0, -1) : '';
				if(!res.has(str)){
					if(sum === init){
						res.add(str);
					}
				}
				if(arr.length){
					for(let k=0; k<arr.length; k++){
						if(i <= arr[k]){
							arr.splice(k, 0, i);
							break;
						}
					}
				}else{
					arr.push(i);
				}
				calculate(n-i, arr, init);
			}
		}
	}
}
function getAll(num){
	calculate(num, [], num);
	//如果num > 1,则最后数量要加多2个不参与calculate计算的,一个是num = num,一个是num = 1 + 1 + ... + 1
	const sum = num > 1 ? res.size + 2 : 1;
	console.log('参与计算的数字:' + num + ',总数:'+sum);
	console.log('计算所得算式:',res);
}
console.time('共用时间:');
getAll(20);
console.timeEnd('共用时间:');
  • 执行结果,如下图
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值