LeetCode39 組合總和的所有情況)

組合總和的所有情礦》》》
在這裏插入圖片描述
在這裏插入圖片描述

  • 數組中的元素不重複同時數組中的元素可以重複取,這種從一個集合中挑選元素的方法來滿足某種條件的問題。一般可以選用遞歸+回溯,選擇了一個條件並在這個條件下走下去,若發現滿足題目的要求,則這條路徑可以作爲一種可能,若走不下去則不能。這條路徑走完了,接着走另外的一條路;同時可以進行剪枝,`當前的情況下一定不滿足最終的結果,不必再走了;搜索問題一般複雜度較高,能剪枝就儘量剪枝,把候選數組拍個序,遇到一個較大的數,如果以這個數位起點都搜索不到結果,後面的數就更搜索不到結果。
package BDyNamicProgramming;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @Author Zhou  jian
 * @Date 2020 ${month}  2020/4/25 0025  13:25
 */
public class Problem39 {

    //求組合的和爲target的所有可能
    public List<List<Integer>> combinationSum(int[] candidates, int target){

        List<List<Integer>> rs = new ArrayList<>();
        List<Integer> r = new ArrayList<>();

        //排序是爲了提前終止搜索
        Arrays.sort(candidates);

        //組合中的數可以重複的取
        fun(candidates,target,rs,r,0);

        return rs;

    }


    //深度優先搜索:
    //這種索索是全排列不是全組合
    //不加start會存在問題
    /*
        [[2, 2, 3], [2, 3, 2], [3, 2, 2], [7]],而示例中的解集只有 [[7], [2, 2, 3]]

        重複的原因是在較深層的節點值考慮了之前考慮過的元素,因此我們需要設置“下一輪搜索的起點"即可

        去重複:
                在搜索的時候,需要設置搜索起點的start,由於一個數可以使用多次,下一層的節點從這個搜索起點開始搜索

                在搜索起點之前start之前,因爲以前的分支搜索過了,所以一定會產生重複

        提前剪樹枝:
                如果一個數位搜索起點都不能搜索到結果,那麼比他還大的數肯定搜索不到結果,基於這個想法,我們可以對輸入數組進行排序,以減少搜索分支

                排序是爲了提高搜索速度,非必要

                搜索問題一般複雜度較高,能剪值就儘量剪值,把候選數組排個序,遇到一個較大的數,如果把這個歌樹爲起點都搜索不到結果,後面的數就更搜索不到

     */

    /**
     *
     * @param candidates 數組輸入
     * @param target    剩餘數值
     * @param rs       結果集變量
     * @param r        從根接地那到任意節點的路徑
     * @param start    本輪搜索的起點下標(這個很關鍵)
     */
    public void fun(int[] candidates,int target,List<List<Integer>> rs,List<Integer> r,int start){

        //符合值相等
        if(target==0){
            //由於r全局只適用到一份,到葉子節點的時候需要做一份拷貝
            rs.add(new ArrayList<>(r));
        }

        if(target<0) return;

        //遞歸+回溯
        for(int i=start;i<candidates.length;i++){

            //在數組有序的前提下剪值
            if(target-candidates[i]<0) break;

            //將當前值加入到list中
            r.add(candidates[i]);

            //組合中的數可以重複的取值,i爲下輪搜索的起始點
            fun(candidates,target-candidates[i],rs,r,i);


           //進行回溯
            r.remove((Object)candidates[i]);
        }


    }

    public static void main(String[] args) {
        int[] arr = {2,3,6,7};
        int target = 7;

        Problem39 problem39 = new Problem39();

        List<List<Integer>> rs = problem39.combinationSum(arr,target);

        System.out.println(rs);

    }



}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章