1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        ?LeetCode刷題實戰(zhàn)40:組合總和 II

        共 4166字,需瀏覽 9分鐘

         ·

        2020-09-16 21:17

        算法的重要性,我就不多說了吧,想去大廠,就必須要經(jīng)過基礎(chǔ)知識和業(yè)務(wù)邏輯面試+算法面試。所以,為了提高大家的算法能力,這個公眾號后續(xù)每天帶大家做一道算法題,題目就從LeetCode上面選 !


        今天和大家聊的問題叫做?組合總和 II,我們先來看題面:

        https://leetcode-cn.com/problems/combination-sum-ii/

        Given a collection of candidate numbers (candidates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.


        Each number in candidates may only be used once in the combination.


        Note:


        All numbers (including target) will be positive integers.

        The solution set must not contain duplicate combinations.

        題意

        給定一個數(shù)組 candidates 和一個目標(biāo)數(shù) target ,找出 candidates 中所有可以使數(shù)字和為 target 的組合。
        candidates 中的每個數(shù)字在每個組合中只能使用一次。
        說明:
        所有數(shù)字(包括目標(biāo)數(shù))都是正整數(shù)。
        解集不能包含重復(fù)的組合。?

        樣例

        示例?1:
        輸入: candidates =?[10,1,2,7,6,1,5], target =?8,
        所求解集為:
        [
        ??[1, 7
        ],
        ??[1, 2, 5],
        ??[2, 6],
        ??[1, 1, 6]
        ]

        示例?2:
        輸入: candidates =?[2,5,2,1,2], target =?5,
        所求解集為:
        [
        ? [1,2,2
        ],
        ? [5]
        ]

        題解

        回溯算法 + 剪枝

        本題解答作者:liweiwei1419
        https://leetcode-cn.com/problems/combination-sum-ii/solution/hui-su-suan-fa-jian-zhi-python-dai-ma-java-dai-m-3/

        這道題與上一問的區(qū)別在于:
        第 39 題:candidates 中的數(shù)字可以無限制重復(fù)被選??;
        第 40 題:candidates 中的每個數(shù)字在每個組合中只能使用一次。
        相同點是:相同數(shù)字列表的不同排列視為一個結(jié)果。

        如何去掉重復(fù)的集合(重點)
        為了使得解集不包含重復(fù)的組合。有以下 2 種方案:
        • 使用 哈希表 天然的去重功能,但是編碼相對復(fù)雜;

        • 這里我們使用和第 39 題和第 15 題(三數(shù)之和)類似的思路:不重復(fù)就需要按 順序 搜索, 在搜索的過程中檢測分支是否會出現(xiàn)重復(fù)結(jié)果 。注意:這里的順序不僅僅指數(shù)組 candidates 有序,還指按照一定順序搜索結(jié)果。




        由第 39 題我們知道,數(shù)組 candidates 有序,也是 深度優(yōu)先遍歷 過程中實現(xiàn)「剪枝」的前提。

        將數(shù)組先排序的思路來自于這個問題:去掉一個數(shù)組中重復(fù)的元素。很容易想到的方案是:先對數(shù)組 升序 排序,重復(fù)的元素一定不是排好序以后相同的連續(xù)數(shù)組區(qū)域的第 1 個元素。也就是說,剪枝發(fā)生在:同一層數(shù)值相同的結(jié)點第 2、3 ... 個結(jié)點,因為數(shù)值相同的第 11 個結(jié)點已經(jīng)搜索出了包含了這個數(shù)值的全部結(jié)果,同一層的其它結(jié)點,候選數(shù)的個數(shù)更少,搜索出的結(jié)果一定不會比第 1個結(jié)點更多,并且是第 1個結(jié)點的子集。(說明:這段文字很拗口,大家可以結(jié)合具體例子,在紙上寫寫畫畫進(jìn)行理解。)


        代碼如下:


        import?java.util.ArrayDeque;
        import?java.util.ArrayList;
        import?java.util.Arrays;
        import?java.util.Deque;
        import?java.util.List;

        public?class?Solution?{

        ????public?List> combinationSum2(int[] candidates, int?target) {
        ????????int?len = candidates.length;
        ????????List> res = new?ArrayList<>();
        ????????if?(len == 0) {
        ????????????return?res;
        ????????}

        ????????// 關(guān)鍵步驟
        ????????Arrays.sort(candidates);

        ????????Deque path = new?ArrayDeque<>(len);
        ????????dfs(candidates, len, 0, target, path, res);
        ????????return?res;
        ????}

        ????/**
        ?????* @param?candidates 候選數(shù)組
        ?????* @param?len 冗余變量
        ?????* @param?begin 從候選數(shù)組的 begin 位置開始搜索
        ?????* @param?target 表示剩余,這個值一開始等于 target,基于題目中說明的"所有數(shù)字(包括目標(biāo)數(shù))都是正整數(shù)"這個條件
        ?????* @param?path 從根結(jié)點到葉子結(jié)點的路徑
        ?????* @param?res
        ?????*/

        ????private?void?dfs(int[] candidates, int?len, int?begin, int?target, Deque path, List> res)?{
        ????????if?(target == 0) {
        ????????????res.add(new?ArrayList<>(path));
        ????????????return;
        ????????}
        ????????for?(int?i = begin; i < len; i++) {
        ????????????// 大剪枝:減去 candidates[i] 小于 0,減去后面的 candidates[i + 1]、candidates[i + 2] 肯定也小于 0,因此用 break
        ????????????if?(target - candidates[i] < 0) {
        ????????????????break;
        ????????????}

        ????????????// 小剪枝:同一層相同數(shù)值的結(jié)點,從第 2 個開始,候選數(shù)更少,結(jié)果一定發(fā)生重復(fù),因此跳過,用 continue
        ????????????if?(i > begin && candidates[i] == candidates[i - 1]) {
        ????????????????continue;
        ????????????}

        ????????????path.addLast(candidates[i]);
        ????????????// 調(diào)試語句 ①
        ????????????// System.out.println("遞歸之前 => " + path + ",剩余 = " + (target - candidates[i]));

        ????????????// 因為元素不可以重復(fù)使用,這里遞歸傳遞下去的是 i + 1 而不是 i
        ????????????dfs(candidates, len, i + 1, target - candidates[i], path, res);

        ????????????path.removeLast();
        ????????????// 調(diào)試語句 ②
        ????????????// System.out.println("遞歸之后 => " + path + ",剩余 = " + (target - candidates[i]));
        ????????}
        ????}

        ????public?static?void?main(String[] args)?{
        ????????int[] candidates = new?int[]{10, 1, 2, 7, 6, 1, 5};
        ????????int?target = 8;
        ????????Solution solution = new?Solution();
        ????????List> res = solution.combinationSum2(candidates, target);
        ????????System.out.println("輸出 => "?+ res);
        ????}
        }


        好了,今天的文章就到這里,如果覺得有所收獲,請順手點個在看或者轉(zhuǎn)發(fā)吧,你們的支持是我最大的動力。


        上期推文:


        LeetCode1-20題匯總,速度收藏!
        LeetCode刷題實戰(zhàn)21:合并兩個有序鏈表
        LeetCode刷題實戰(zhàn)23:合并K個升序鏈表
        LeetCode刷題實戰(zhàn)24:兩兩交換鏈表中的節(jié)點
        LeetCode刷題實戰(zhàn)25:K 個一組翻轉(zhuǎn)鏈表
        LeetCode刷題實戰(zhàn)26:刪除排序數(shù)組中的重復(fù)項
        LeetCode刷題實戰(zhàn)27:移除元素
        LeetCode刷題實戰(zhàn)28:實現(xiàn) strStr()
        LeetCode刷題實戰(zhàn)29:兩數(shù)相除
        LeetCode刷題實戰(zhàn)30:串聯(lián)所有單詞的子串
        LeetCode刷題實戰(zhàn)31:下一個排列
        LeetCode刷題實戰(zhàn)32:最長有效括號
        LeetCode刷題實戰(zhàn)33:搜索旋轉(zhuǎn)排序數(shù)組
        LeetCode刷題實戰(zhàn)34:在排序數(shù)組中查找元素
        LeetCode刷題實戰(zhàn)35:搜索插入位置
        LeetCode刷題實戰(zhàn)36:有效的數(shù)獨
        LeetCode刷題實戰(zhàn)37:解數(shù)獨
        LeetCode刷題實戰(zhàn)38:外觀數(shù)列
        LeetCode刷題實戰(zhàn)39:組合總和


        瀏覽 24
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            黄色一级操逼视频 | 流氓片日本中文字幕 | 免费看欧美操逼 | 亚洲香蕉视频观看视频 | 91艹逼| 最新草逼打炮 | 《甜性涩爱》完整版在线播放 | 日韩丰满女教师av | 日本三级日本三级韩国三级视 | 男人操女生 |