簡單易懂回溯算法


一、什么是回溯算法

回溯算法實際上一個類似枚舉的搜索嘗試過程,主要是在搜索嘗試過程中尋找問題的解,當發現已不滿足求解條件時,就“回溯”返回,嘗試別的路徑。許多復雜的,規模較大的問題都可以使用回溯法,有“通用解題方法”的美稱。

回溯算法實際上一個類似枚舉的深度優先搜索嘗試過程,主要是在搜索嘗試過程中尋找問題的解,當發現已不滿足求解條件時,就“回溯”返回(也就是遞歸返回),嘗試別的路徑。

二、回溯算法思想

  回溯法一般都用在要給出多個可以實現最終條件的解的最終形式。回溯法要求對解要添加一些約束條件。總的來說,如果要解決一個回溯法的問題,通常要確定三個元素:

1、選擇。對於每個特定的解,肯定是由一步步構建而來的,而每一步怎么構建,肯定都是有限個選擇,要怎么選擇,這個要知道;同時,在編程時候要定下,優先或合法的每一步選擇的順序,一般是通過多個if或者for循環來排列。

2、條件。對於每個特定的解的某一步,他必然要符合某個解要求符合的條件,如果不符合條件,就要回溯,其實回溯也就是遞歸調用的返回。

3、結束。當到達一個特定結束條件時候,就認為這個一步步構建的解是符合要求的解了。把解存下來或者打印出來。對於這一步來說,有時候也可以另外寫一個issolution函數來進行判斷。注意,當到達第三步后,有時候還需要構建一個數據結構,把符合要求的解存起來,便於當得到所有解后,把解空間輸出來。這個數據結構必須是全局的,作為參數之一傳遞給遞歸函數。

三、遞歸函數的參數的選擇,要遵循四個原則

1、必須要有一個臨時變量(可以就直接傳遞一個字面量或者常量進去)傳遞不完整的解,因為每一步選擇后,暫時還沒構成完整的解,這個時候這個選擇的不完整解,也要想辦法傳遞給遞歸函數。也就是,把每次遞歸的不同情況傳遞給遞歸調用的函數。

2、可以有一個全局變量,用來存儲完整的每個解,一般是個集合容器(也不一定要有這樣一個變量,因為每次符合結束條件,不完整解就是完整解了,直接打印即可)。

3、最重要的一點,一定要在參數設計中,可以得到結束條件。一個選擇是可以傳遞一個量n,也許是數組的長度,也許是數量,等等。

4、要保證遞歸函數返回后,狀態可以恢復到遞歸前,以此達到真正回溯。

四、學習例題

1.給出 n 代表生成括號的對數,請你寫出一個函數,使其能夠生成所有可能的並且有效的括號組合。

例如,給出 = 3,生成結果為:

[

  "((()))",

  "(()())",

  "(())()",

  "()(())",

  "()()()"

]

 

2.思路

首先利用回溯枚舉出所有括號的可能性,然后進行判斷是否符合要求(n對並且是有效的括號組合),就添加到list表格中。

對於遞歸函數變量需要全局變量列表list:用來存儲符合要求的括號組合。

                    局部變量temp:表示當前函數的括號組成樣式。

                    計數器x:判斷遞歸次數,限制其底界。

                    總的形成括號對數n。

3.代碼(力扣中國第22題)

public List<String> generateParenthesis(int n) {
        List<String> list=new ArrayList<String>();
        add_list(list,"(", 1, n*2);       
        return list;
    }
    
    //書寫遞歸函數
    
    public void add_list(List<String> list,String temp,int x,int n)    
    {
        x++;
        if(x<=n)
        {
          add_list(list,temp+"(",x,n);
          add_list(list,temp+")",x,n);
            
        }
        if(x>n)
        {
            //在這里寫判斷條件是否負荷有效的括號組合
            char[] k=temp.toCharArray();
            //計數器
            int timer=0;
            for(int i=0;i<k.length;i++)
            {
                if(timer<0||timer>n/2)
                {
                    return;
                }
                else
                {
                    if(k[i]=='(')
                      {
                          timer++;
                      }else
                      {
                          timer--;                          
                      }
                }             
            }
            if(timer==0)
            list.add(temp);
        }
        
    }

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM