
- 資料結構與演算法
- 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
廣告