【LeetCode】No.39 Combination Sum

鏈接:https://leetcode.com/problems/combination-sum/

Given a set of candidate numbers (candidates) (without duplicates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.
The same repeated number may be chosen from candidates unlimited number of times.
Note:

  • All numbers (including target) will be positive integers.
  • The solution set must not contain duplicate combinations.

題目描述

先說一下題目:給定一個數(shù)組薇搁,里面只含有無重復的正整數(shù)欧漱,然后給定一個target,從數(shù)組里選取一些數(shù),使其和為target稠集,每個數(shù)可以選擇多次。求出所有這樣的組合续捂。比如說:
數(shù)組:【2眷蜈,3,6隅俘,7】
target:7
結果:【2邻奠,2笤喳,3】和【7】

數(shù)組:【2,3碌宴,5】
target:8
結果:【2杀狡,2,2贰镣,2】呜象、【2,3碑隆,3】和【3恭陡,5】

思路

【2,3上煤,6休玩,7】為例,target = 7
先對數(shù)組進行排序劫狠。
首先【2】哥捕,還剩下 7 - 2 = 5 > 0,
再取2嘉熊,變?yōu)?code>【2遥赚,2】,還剩下 5 - 2 = 3 > 0,
再取2,變?yōu)?code>【2语婴,2,2】愧薛,還剩下 3 - 2 = 1 > 0,
再取2衫画,變?yōu)?code>【2毫炉,2,2削罩,2】瞄勾,還剩下1 - 2 = -1 < 0,由于所有的數(shù)都是正數(shù)弥激,所以回溯进陡,去掉最后一個2,變?yōu)?code>【2微服,2趾疚,2】,還剩下1。
此時開始取下一個數(shù):
取3糙麦,變?yōu)?code>【2辛孵,2,2赡磅,3】還剩下1 - 3 = -2 < 0魄缚,再回溯,去掉最后一個3仆邓,變?yōu)?code>【2,2伴鳖,2】节值,還剩下1。
我們發(fā)現(xiàn)榜聂,在【2搞疗,2,2】的情況下须肆,【2匿乃,2,2豌汇,6】幢炸、【2,2拒贱,2宛徊,7】都不滿足。

再回溯逻澳,變?yōu)?code>【2闸天,2】,還剩下3斜做,取下一個數(shù):
取3苞氮,變?yōu)?code>【2,2瓤逼,3】笼吟,3 - 3 = 0,符合條件霸旗。
之后再取3及后面的數(shù)都不滿足: [2赞厕,2,3定硝,3】皿桑、【2,2,3诲侮,6】镀虐、【2,2沟绪,3刮便,7】
回溯绽慈,去掉最后一個數(shù)3恨旱,變?yōu)?code>【2,2】坝疼,剩下3 > 0
此時再取3后面的數(shù)都不滿足搜贤,【2,2钝凶,6】仪芒、【2,2耕陷,7】都不滿足掂名。

再回溯,變?yōu)?code>【2】哟沫,剩下5饺蔑,取下一個數(shù):
取6,變?yōu)?code>【2嗜诀,6】膀钠,5 - 6 < 0,回溯裹虫,
再取7肿嘲,變?yōu)?code>【2,7】不符合筑公,回溯雳窟。
變?yōu)?code>【2】,此時已經取完匣屡,再回溯封救,變?yōu)榭?code>【】。

取下一個數(shù)捣作,變?yōu)?code>【3】誉结,7 - 3 = 4 > 0,
再取3券躁,【3惩坑,3】掉盅,4-3=1>0,
再取3以舒,【3趾痘,3,3】蔓钟,1-3=-2<0永票,回溯。刪去最后一個3滥沫,變?yōu)?code>【3侣集,3】。
此時取后面的數(shù)都不行兰绣。再回溯世分,刪除最后一個3,變?yōu)?code>【3】狭魂。
取下一個6罚攀,【3党觅,6】雌澄,7-3-6<0,回溯杯瞻。變?yōu)?code>【3】镐牺。再回溯,變?yōu)?code>【】魁莉。
取下一個6睬涧,【6】,7-6=1>0旗唁,
再取6畦浓,【6,6】检疫,1-6<0讶请,回溯,再回溯屎媳,變?yōu)榭?code>【】夺溢。
去下一個7,【7】烛谊,7-7=0风响,符合。
丹禀。状勤。鞋怀。

代碼

public List<List<Integer>> combinationSum(int[] candidates, int target) {
    //res用來存放所有的結果
    List<List<Integer>> res = new LinkedList<>();
    //對數(shù)組進行排序
    Arrays.sort(candidates);
    helper(candidates, new LinkedList<Integer>(), res, 0, target);
    return res;
}

//list代表臨時選取的數(shù)組成的列表,start是開始迭代的index荧降,remain=target減去list里所有數(shù)的和接箫。
private void helper(int[] nums, List<Integer> list, List<List<Integer>> res, int start, int remain){
    //remain小于0,說明list里面所有的數(shù)的和已經大于target朵诫,直接返回
    if(remain < 0) return;
    //remain等于0辛友,說明list里面所有的數(shù)的和等于target,將該數(shù)組復制一份放進結果集中剪返。
    if(remain == 0){
        res.add(new LinkedList<>(list));
        return;
    }
    //remain大于0废累,還需要往list里面加數(shù),從start開始加脱盲。
    for(int i = start; i < nums.length; ++i){
        list.add(nums[i]);
        //因為選取的數(shù)可以重復邑滨,所以這里還是i,而不是i+1钱反。
        helper(nums, list, res, i, remain - nums[i]);
        list.remove(list.size() - 1);
    }
}

可以看到掖看,helper方法在兩種情況下return:remain < 0remain == 0,因為數(shù)組中的數(shù)已經排序面哥、唯一且大于0哎壳,所以這兩種情況出現(xiàn)之后,再往list里面加數(shù)都不滿足list里元素的和等于target尚卫,所以返回之后归榕,去掉list里的最后一個數(shù)(list.remove(list.size() - 1)),從下一個數(shù)繼續(xù)遍歷吱涉。

舉一反三

這道題還有一個變形刹泄,鏈接:https://leetcode.com/problems/combination-sum-ii/
這道題的不同點就是:
1、給定數(shù)組中的數(shù)可以重復
2怎爵、每個數(shù)只能選一次
比如說:

Input: candidates = [10,1,2,7,6,1,5], target = 8,
A solution set is:
[
  [1, 7],
  [1, 2, 5],
  [2, 6],
  [1, 1, 6]
]

直接看代碼:

    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<List<Integer>> res = new LinkedList<>();
        Arrays.sort(candidates);
        helper(candidates, new LinkedList<Integer>(), res, 0, target);
        return res;
    }
    
    private void helper(int[] nums, List<Integer> list, List<List<Integer>> res, int start, int remain){
        if(remain < 0) return;
        if(remain == 0){
            res.add(new LinkedList<>(list));
        }
        for(int i = start; i < nums.length; ++i){
            if(i > start && nums[i] == nums[i - 1]) {
                //System.out.println("i:" + i + " num: " + nums[i]);
                continue;
            }
            list.add(nums[i]);
            //list.forEach(System.out::print);
            //System.out.println();
            //由于每個數(shù)只能用一次特石,所以這里直接 i + 1,
            helper(nums, list, res, i + 1, remain - nums[i]);
            list.remove(list.size() - 1);
        }
    }

不同的地方有兩點:
一個是helper(nums, list, res, i + 1, remain - nums[i])鳖链,在選取一個數(shù)之后姆蘸,再選取下一個,這里是i + 1撒轮。
另一個是if(i > start && nums[i] == nums[i - 1]) continue;乞旦,這里是因為數(shù)組中有重復的數(shù),而我們的結果集中不能存在一樣的選取組合题山。比如說[10,1,2,7,6,1,5] target = 8兰粉,[1,2顶瞳,5]是一個選擇方式玖姑,但是因為1有兩個愕秫,所以我們只能取1個。

自己覺得邏輯比較亂的話可以自己打印一下關鍵信息焰络,好好理一理戴甩。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市闪彼,隨后出現(xiàn)的幾起案子甜孤,更是在濱河造成了極大的恐慌,老刑警劉巖畏腕,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缴川,死亡現(xiàn)場離奇詭異,居然都是意外死亡描馅,警方通過查閱死者的電腦和手機把夸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來铭污,“玉大人恋日,你說我怎么就攤上這事∴谀” “怎么了岂膳?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長刁绒。 經常有香客問我闷营,道長烤黍,這世上最難降的妖魔是什么知市? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮速蕊,結果婚禮上嫂丙,老公的妹妹穿的比我還像新娘。我一直安慰自己规哲,他們只是感情好跟啤,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著唉锌,像睡著了一般隅肥。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上袄简,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天腥放,我揣著相機與錄音,去河邊找鬼绿语。 笑死秃症,一個胖子當著我的面吹牛候址,可吹牛的內容都是我干的。 我是一名探鬼主播种柑,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼岗仑,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了聚请?” 一聲冷哼從身側響起荠雕,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎驶赏,沒想到半個月后舞虱,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡母市,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年矾兜,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片患久。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡椅寺,死狀恐怖,靈堂內的尸體忽然破棺而出蒋失,到底是詐尸還是另有隱情返帕,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布篙挽,位于F島的核電站荆萤,受9級特大地震影響,放射性物質發(fā)生泄漏铣卡。R本人自食惡果不足惜链韭,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望煮落。 院中可真熱鬧敞峭,春花似錦、人聲如沸蝉仇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽轿衔。三九已至沉迹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間害驹,已是汗流浹背鞭呕。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留裙秋,地道東北人琅拌。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓缨伊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親进宝。 傳聞我的和親對象是個殘疾皇子刻坊,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內容