一道算法题,求更好的解法
问题(阿里2010年实习):
给定一个数t,以及n个整数,在这n个整数中找到相加之和为t的所有组合,例如t = 4,n = 6,这6个数为[4, 3, 2, 2, 1, 1],这样输出就有4个不同的组合,它们的相加之和为4:4, 3+1, 2+2, and 2+1+1。请设计一个高效算法实现这个需求。
下面,给出一种解法:

#include <stdio.h>
#define LEN 20
int path[LEN];
int arr[LEN] = {1, 1, 1, 2, 2, 3, 4, 4, 5, 5, 5, 8, 8, 8, 10, 10, 10, 12, 12, 12};
void clearpath()
{
int i;
for (i = 0; i < LEN; i++)
{
path[i] = 0;
}
}
void out_put()
{
int i;
for (i = LEN-1; i >= 0; i--)
{
if(path[i] == 1)
printf(" %d ", arr[i]);
}
printf("\n");
}
/*算法:
**q(n, t)表示从arr[0]...arr[n]中选出和为t的子集,则
**q(n, t) = q(n-1, t-arr[n]) + q(n-1, t)
*/
void q(int n, int t, int flag)
{
if(t < 0)
return;
path[n+1] = flag;
if(n == 0)
{
if(t == 0)
{
path[n] = 0; //不包含arr[0]
out_put();
}
else if(arr[n] == t)
{
path[n] = 1;//包含arr[0]
out_put();
}
}
else
{
q(n-1, t-arr[n], 1); //包含arr[n]
q(n-1, t, 0); //不包含arr[n]
}
}
void subsum(int len, int t)
{
q(len - 1, t - arr[len], 1);
q(len - 1, t, 0);
}
int main()
{
int t = 20;
clearpath();
subsum(LEN - 1, t);
return 0;
}
#define LEN 20
int path[LEN];
int arr[LEN] = {1, 1, 1, 2, 2, 3, 4, 4, 5, 5, 5, 8, 8, 8, 10, 10, 10, 12, 12, 12};
void clearpath()
{
int i;
for (i = 0; i < LEN; i++)
{
path[i] = 0;
}
}
void out_put()
{
int i;
for (i = LEN-1; i >= 0; i--)
{
if(path[i] == 1)
printf(" %d ", arr[i]);
}
printf("\n");
}
/*算法:
**q(n, t)表示从arr[0]...arr[n]中选出和为t的子集,则
**q(n, t) = q(n-1, t-arr[n]) + q(n-1, t)
*/
void q(int n, int t, int flag)
{
if(t < 0)
return;
path[n+1] = flag;
if(n == 0)
{
if(t == 0)
{
path[n] = 0; //不包含arr[0]
out_put();
}
else if(arr[n] == t)
{
path[n] = 1;//包含arr[0]
out_put();
}
}
else
{
q(n-1, t-arr[n], 1); //包含arr[n]
q(n-1, t, 0); //不包含arr[n]
}
}
void subsum(int len, int t)
{
q(len - 1, t - arr[len], 1);
q(len - 1, t, 0);
}
int main()
{
int t = 20;
clearpath();
subsum(LEN - 1, t);
return 0;
}
该算法的时间复杂度为指数级(但实际情况应该好很多,与t相关),而且最大的问题在于,无法去掉重复的组合。求更好的解法。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
2009-05-14 字节对齐算法