leadcode的Hot100系列--78. 子集--回溯

上一篇說了使用位運算來進行子集輸出,這裏使用回溯的方法來進行排序。
回溯的思想,個人理解就是:數組

把解的全部狀況轉換爲樹或者圖,而後用深度優先的原則來對全部的狀況進行遍歷解析。函數

固然,由於問題中會包涵這各類各樣的限制條件,咱們能夠用這些限制條件去減小遍歷的分支。
其實,比較著名的就是0-1揹包問題,這個揹包問題以後再說,這裏先看排列組合。code

假設咱們的數組爲[6,7,8],依然使用0來表示當前數字不存在,用1來表示當前數字存在,咱們就能夠畫出這樣一個樹:
blog

這裏使用遞歸來生成對應的flag標記,重點是backtrack函數:排序

#include <stdio.h>

int x[] = {6,7,8};   // 須要排列的數組
int y[] = {0,0,0};   // 存放flag標記
int level = 3;       // 有3個數字須要進行排列,對應的就須要排3層

void show()
{
    for (int i=0; i<level; i++)
    {
        printf("flag : %d ", y[i]);
    }
    printf("\n");
}

void backtrack (int t)
{
    if (t == level)   // 當遍歷深度等於level的時候,說明遍歷完成,獲得一組完整的flag標記
        show();
    else  
        for (int i=0;i<=1;i++)   // 這裏先生成0標記,再生成1標記
        {
            y[t]=i;            //  記錄當前層是否存在,0存在,1不存在
            backtrack(t+1);   // 遞歸遍歷下一層,這裏能夠根據題目限制來判斷是否須要繼續下一層的遍歷,能夠減小遍歷次數
        }
}

int main(void)
{
    backtrack(0);
    return 0;
}

輸出結果爲:
0 0 0 
0 0 1 
0 1 0 
0 1 1 
1 0 0 
1 0 1 
1 1 0 
1 1 1

回溯的基本就那麼一個思想,那限制條件怎麼用呢?
好比,我有10元錢,這裏有三個物品,價格分別是8元,5元,2元,10元,
問,這10元錢能夠有哪些買法?
這裏存在的一個限制就是:總數不能超過10。遞歸

#include <stdio.h>

#define TOTAL 10  // 總數最多爲10

int x[] = {8,5,2,10};  // 價格
int y[] = {0,0,0,0};
int level = 4;

void show()
{
    int n=0;
    for (int i=0; i<level; i++)   // 計算總價格是否超過10
    {
        n += y[i] * x[i];
    }
    if (TOTAL < n)
    {
        return;
    }
    for (int i=0; i<level; i++)   // 這裏直接打印符合條件的價格
    {
        printf("%d ", y[i]*x[i]);
    }
    printf("\n");
}

void backtrack (int t)
{
    if (t == level)
        show();
    else  
        for (int i=0;i<=1;i++) 
        {
            y[t]=i;
            int n = 0;
            for (int j=0; j<t; j++)  // 這裏先計算一下當前價格是多少
            {
                n = y[j] * x[j];
            }
            if (TOTAL > n)       // 若是當前價格已經超了,就不須要再遞歸下一層(由於不論下一層是否存在,總價格必然會超),不然繼續遞歸
                backtrack(t+1);
        }
}

int main()
{
    backtrack(0);
    return 0;
}
結果爲:
0 0 0 0 
0 0 0 10 
0 0 2 0 
0 5 0 0 
0 5 2 0 
8 0 0 0 
8 0 2 0
相關文章
相關標籤/搜索