- 資料結構與演算法
- DSA - 首頁
- DSA - 概述
- DSA - 環境搭建
- DSA - 演算法基礎
- DSA - 漸進分析
- 資料結構
- DSA - 資料結構基礎
- DSA - 資料結構和型別
- DSA - 陣列資料結構
- 連結串列
- DSA - 連結串列資料結構
- DSA - 雙向連結串列資料結構
- DSA - 迴圈連結串列資料結構
- 棧與佇列
- DSA - 棧資料結構
- DSA - 表示式解析
- DSA - 佇列資料結構
- 搜尋演算法
- DSA - 搜尋演算法
- DSA - 線性搜尋演算法
- DSA - 二分搜尋演算法
- DSA - 插值搜尋
- DSA - 跳躍搜尋演算法
- DSA - 指數搜尋
- DSA - 斐波那契搜尋
- DSA - 子列表搜尋
- DSA - 雜湊表
- 排序演算法
- DSA - 排序演算法
- DSA - 氣泡排序演算法
- DSA - 插入排序演算法
- DSA - 選擇排序演算法
- DSA - 歸併排序演算法
- DSA - 希爾排序演算法
- DSA - 堆排序
- DSA - 桶排序演算法
- DSA - 計數排序演算法
- DSA - 基數排序演算法
- DSA - 快速排序演算法
- 圖資料結構
- DSA - 圖資料結構
- DSA - 深度優先遍歷
- DSA - 廣度優先遍歷
- DSA - 生成樹
- 樹資料結構
- DSA - 樹資料結構
- DSA - 樹的遍歷
- DSA - 二叉搜尋樹
- DSA - AVL樹
- DSA - 紅黑樹
- DSA - B樹
- DSA - B+樹
- DSA - 伸展樹
- DSA - 字典樹
- DSA - 堆資料結構
- 遞迴
- DSA - 遞迴演算法
- DSA - 使用遞迴解決漢諾塔問題
- DSA - 使用遞迴求斐波那契數列
- 分治法
- DSA - 分治法
- DSA - 最大最小問題
- DSA - Strassen矩陣乘法
- DSA - Karatsuba演算法
- 貪心演算法
- DSA - 貪心演算法
- DSA - 旅行商問題(貪心演算法)
- DSA - Prim最小生成樹
- DSA - Kruskal最小生成樹
- DSA - Dijkstra最短路徑演算法
- DSA - 地圖著色演算法
- DSA - 分數揹包問題
- DSA - 帶截止日期的作業排序
- DSA - 最佳合併模式演算法
- 動態規劃
- DSA - 動態規劃
- DSA - 矩陣鏈乘法
- DSA - Floyd-Warshall演算法
- DSA - 0-1揹包問題
- DSA - 最長公共子序列演算法
- DSA - 旅行商問題(動態規劃)
- 近似演算法
- DSA - 近似演算法
- DSA - 頂點覆蓋演算法
- DSA - 集合覆蓋問題
- DSA - 旅行商問題(近似演算法)
- 隨機化演算法
- DSA - 隨機化演算法
- DSA - 隨機化快速排序演算法
- DSA - Karger最小割演算法
- DSA - Fisher-Yates洗牌演算法
- DSA有用資源
- DSA - 問答
- DSA - 快速指南
- DSA - 有用資源
- DSA - 討論
子集和問題
子集和問題
在**子集和問題**中,給定一個包含一些非負整數元素的集合。同時還提供一個和值,我們的任務是找到給定集合的所有可能的子集,其元素之和與給定的和值相同。
**集合:**在數學術語中,**集合**被定義為相似型別物件的集合。集合的實體或物件必須透過相同的規則相互關聯。
**子集:**假設有兩個集合,即集合P和集合Q。當且僅當集合P的所有元素也屬於集合Q時,集合P被稱為集合Q的子集,反之則不一定成立。
輸入輸出場景
假設給定的集合和和值如下:
Set = {1, 9, 7, 5, 18, 12, 20, 15}
sum value = 35
給定集合的所有可能的子集,其中每個子集的每個元素的和與給定的和值相同,如下所示:
{1 9 7 18}
{1 9 5 20}
{5 18 12}
回溯法解決子集和問題
在解決子集和問題的樸素方法中,演算法生成所有可能的排列,然後逐個檢查有效解。每當一個解滿足約束條件時,將其標記為解的一部分。
在解決子集和問題時,回溯法用於選擇有效的子集。當一個專案無效時,我們將回溯以獲取先前的子集,並新增另一個元素以獲得解。
在最壞情況下,回溯法可能會生成所有組合,但是,通常情況下,它的效能優於樸素方法。
請按照以下步驟使用回溯法解決子集和問題:
首先,取一個空子集。
將下一個元素(索引為0)包含到空集中。
如果子集等於和值,則將其標記為解的一部分。
如果子集不是解並且小於和值,則向子集中新增下一個元素,直到找到有效的解。
現在,轉到集合中的下一個元素並檢查另一個解,直到所有組合都已嘗試過。
示例
在本示例中,我們將說明如何在各種程式語言中解決子集和問題。
#include <stdio.h>
#define SIZE 7
void displaySubset(int subSet[], int size) {
for(int i = 0; i < size; i++) {
printf("%d ", subSet[i]);
}
printf("\n");
}
void subsetSum(int set[], int subSet[], int n, int subSize, int total, int nodeCount ,int sum) {
if( total == sum) {
//print the subset
displaySubset(subSet, subSize);
//for other subsets
if (subSize != 0)
subsetSum(set,subSet,n,subSize-2,total-set[nodeCount],nodeCount+1,sum);
return;
}else {
//find node along breadth
for( int i = nodeCount; i < n; i++ ) {
subSet[subSize] = set[i];
//do for next node in depth
subsetSum(set,subSet,n,subSize+1,total+set[i],i+1,sum);
}
}
}
void findSubset(int set[], int size, int sum) {
//create subset array to pass parameter of subsetSum
int subSet[size];
subsetSum(set, subSet, size, 0, 0, 0, sum);
}
int main() {
int weights[] = {1, 9, 7, 5, 18, 12, 20, 15};
int size = SIZE;
findSubset(weights, size, 35);
return 0;
}
#include <iostream>
using namespace std;
void displaySubset(int subSet[], int size) {
for(int i = 0; i < size; i++) {
cout << subSet[i] << " ";
}
cout << endl;
}
void subsetSum(int set[], int subSet[], int n, int subSize, int total, int nodeCount, int sum) {
if( total == sum) {
//print the subset
displaySubset(subSet, subSize);
//for other subsets
subsetSum(set, subSet, n, subSize-1, total-set[nodeCount], nodeCount+1,sum);
return;
}else {
//find node along breadth
for( int i = nodeCount; i < n; i++ ) {
subSet[subSize] = set[i];
//do for next node in depth
subsetSum(set, subSet, n, subSize+1, total+set[i], i+1, sum);
}
}
}
void findSubset(int set[], int size, int sum) {
//create subset array to pass parameter of subsetSum
int *subSet = new int[size];
subsetSum(set, subSet, size, 0, 0, 0, sum);
delete[] subSet;
}
int main() {
int weights[] = {1, 9, 7, 5, 18, 12, 20, 15};
int size = 7;
findSubset(weights, size, 35);
}
public class Main {
static void displaySubset(int subSet[], int size) {
for(int i = 0; i < size; i++) {
System.out.print(subSet[i] + " ");
}
System.out.println();
}
static void subsetSum(int set[], int subSet[], int n, int subSize, int total, int nodeCount ,int sum) {
if( total == sum) {
//print the subset
displaySubset(subSet, subSize);
//for other subsets
if (subSize != 0)
subsetSum(set,subSet,n,subSize-1,total-set[nodeCount],nodeCount+1,sum);
return;
} else {
//find node along breadth
for( int i = nodeCount; i < n; i++ ) {
subSet[subSize] = set[i];
//do for next node in depth
subsetSum(set,subSet,n,subSize+1,total+set[i],i+1,sum);
}
}
}
static void findSubset(int set[], int size, int sum) {
//create subset array to pass parameter of subsetSum
int subSet[] = new int[size];
subsetSum(set, subSet, size, 0, 0, 0, sum);
}
public static void main(String[] args) {
int weights[] = {1, 9, 7, 5, 18, 12, 20, 15};
int size = 7;
findSubset(weights, size, 35);
}
}
def displaySubset(subSet, size):
for i in range(size):
print(subSet[i], end=" ")
print()
def subsetSum(set, subSet, n, subSize, total, nodeCount, sum):
if total == sum:
#print the subset
displaySubset(subSet, subSize)
#for other subsets
if subSize != 0:
subsetSum(set, subSet, n, subSize-1, total-set[nodeCount], nodeCount+1, sum)
return
else:
#find node along breadth
for i in range(nodeCount, n):
subSet[subSize] = set[i]
#do for next node in depth
subsetSum(set, subSet, n, subSize+1, total+set[i], i+1, sum)
def findSubset(set, size, sum):
#create subset array to pass parameter of subsetSum
subSet = [0]*size
subsetSum(set, subSet, size, 0, 0, 0, sum)
if __name__ == "__main__":
weights = [1, 9, 7, 5, 18, 12, 20, 15]
size = 7
findSubset(weights, size, 35)
輸出
1 9 7 18 1 9 5 20 5 18 12
廣告