部分和问题

题目来源

挑战程序设计竞赛(第二版)

语言

C/C++

题目

部分和问题

描述

给定整数 a1, a2, ..., an,判断是否可以从中选出若干数,使它们的和恰好为 k。

样例1

输入:

n = 4

a = {1, 2, 4, 7};

k = 13

输出:

Yes

样例2

输入:

n = 4

a = {1, 2, 4, 7};

k = 15

输出:

No

思路

这道题目可以分解成两步,第一步先选取若干数,第二步对这些数进行求和判断是否等于 k。

以样例 1 为例,输入 4 个数,选取其中的若干数,求和,判断其和是否为 13。从头对这 4 个数进行依次访问,既然要选取若干数,那么每个数都有被选中或者弃选的可能(2 种情况),可以将整个选数的情况看做一棵二叉树,从根结点到叶子结点的路径就成为一组选数的可能。

部分和问题_第1张图片

(该图前两个数的情况)

只需要对这棵树进行遍历,每次遍历到叶子结点时判断一下当前的 sum 是否与 13 相等,若相等为找到一组数据,不相等继续遍历,若这棵树从头遍历一遍没有出现想要的结果,则判定无结果。

 

对这棵树进行遍历,我们可以使用深度优先搜索(DFS)。

代码

#include 
#define MAXBUF 256

int n = 4;
int k = 13;
int a[MAXBUF] = {1, 2, 4, 7}; 

bool dfs(int i, int sum);

int main(int argc, char *argv[]) {
	using namespace std;
	
	if (dfs(0, 0)){
		cout << "Yes";
	} 
	else
		cout << "No";
	
	return 0;
}

// i 为第 i 个数据 a[i-1],sum 为当前部分和 
bool dfs(int i, int sum)
{
	if (i == n){	// DFS 停止条件 
		return sum == k;
	} 
	if (dfs(i + 1, sum)){	// 下个数据不加 
		return true;
	}
	if (dfs(i + 1, sum + a[i])){	// 下个数据加 
		return true;
	} 
	
	return false;	// 遍历所有结果都无符合条件 
} 

时间复杂度

对 n 个数进行遍历,每个数都有 2 种情况,因此时间复杂度为 O(2^n)。

所涉及的知识点

深度优先搜索(DFS)

 

 

 

 

你可能感兴趣的:(数据结构与算法)