代碼隨想錄算法訓(xùn)練營(yíng)第二十七天|39. 組合總和、40.組合總和II、131.分割回文串

39. 組合總和

39. 組合總和 - 力扣(LeetCode)
本題和之前組合題不同在于,可以取重復(fù)的值,那么for循環(huán)里的遞歸還是從i開始,另外沒有規(guī)定取k個(gè),那么遞歸結(jié)束條件就是sum==target即可,另外剪枝操作是先將數(shù)組排序,然后在for循環(huán)里加條件,如果sum>target就break,注意這個(gè)地方和之前的組合總和3不同

class Solution {
    List<List<Integer>> result = new ArrayList<>();
    List<Integer> path = new LinkedList<>();

    public List<List<Integer>> combinationSum(int[] candidates, int target){
        Arrays.sort(candidates);
        backTracking(candidates, target, 0, 0);
        return result;
    }

    public void backTracking(int[] candidates, int target, int sum, int startIndex) {
        if (sum == target) {
            result.add(new ArrayList<>(path));
            return;
        }
        for (int i=startIndex; i<candidates.length; i++) {
            sum += candidates[i];
            if (sum > target) break;
            path.add(candidates[i]);
            //因?yàn)槭强梢灾貜?fù)的,所以從i開始
            backTracking(candidates, target, sum, i);
            sum -= candidates[i];
            path.removeLast();
        }
    }
}

40.組合總和II

40. 組合總和 II - 力扣(LeetCode)
本題要求數(shù)組中可以有重復(fù)數(shù)值,但是最后的結(jié)果中不能有重復(fù)的組合,所以中間過程需要去重,先把數(shù)組排序,進(jìn)行數(shù)層去重,比如兩個(gè)1相鄰,第一個(gè)1遍歷后,第二個(gè)1就可以不用遍歷了,因?yàn)榈谝粋€(gè)1遍歷的過程已經(jīng)包含了第二個(gè)1遍歷的結(jié)果

class Solution {
    public List<List<Integer>> result = new ArrayList<>();
    public List<Integer> path = new LinkedList<>();
    boolean[] used;

    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        used = new boolean[candidates.length];   
        Arrays.fill(used, false);
        Arrays.sort(candidates);
        backTracking(candidates, target, 0, 0);
        return result;
    }

    public void backTracking(int[] candidates, int target, int sum, int startIndex) {
        //這里沒有return結(jié)束,因?yàn)閏andidates里有重復(fù)的值,后面可能還會(huì)有結(jié)果
        if (sum == target) {
            result.add(new ArrayList<>(path));
        }
        for (int i = startIndex; i < candidates.length; i++) {
            //去重:used=true代表在樹枝上有重復(fù)的值,不需要去重;used=false代表在數(shù)層上有重復(fù)的值,又是回溯產(chǎn)生的,需要去重
            if (i > 0 && candidates[i] == candidates[i-1] && !used[i-1]) {
                continue;
            }
            sum += candidates[i];
            if (sum > target) {
                break;
            }
            used[i] = true;
            path.add(candidates[i]);
            backTracking(candidates, target, sum, i+1);
            used[i] = false;
            sum -= candidates[i];
            path.removeLast();
        }
    }
}

131.分割回文串

131. 分割回文串 - 力扣(LeetCode)
本題在判斷分割的字符串是回文子串后,將其加入path中,并且將判斷分割到最后是否合格的過程,放到for循環(huán)中

class Solution {

    List<String> path = new LinkedList<>();
    List<List<String>> result = new ArrayList<>();

    public List<List<String>> partition(String s) {
        backTracking(s, 0);
        return result;
    }

    public void backTracking(String str, int startIndex) {
        if (startIndex >= str.length()) {
            result.add(new ArrayList<>(path));
            return;
        }
        for (int i = startIndex; i < str.length(); i++) {
            if (isPalindrome(str, startIndex, i)) {
                String str1 = str.substring(startIndex, i + 1);
                path.add(str1);
            } else {
                continue;
            }
            backTracking(str, i + 1);
            path.removeLast();
        }
    }

    // 判斷是否是回文子串,左閉右閉區(qū)間
    public boolean isPalindrome(String str, int start, int end) {
        for (int i = start, j = end; i < j; i++, j--) {
            if (str.charAt(i) != str.charAt(j)) {
                return false;
            }
        }
        return true;
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容