Day26 | 回溯算法PART2

39. 组合总和

计算一个vector的总和有没有简单的方法。。每次都单独写一个函数出来

待补充:

class Solution {
public:
    vector<vector<int>> result;
    vector<int> each;
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        backTrace(target, candidates, 0);
        return result;
    }
    void backTrace(int target, vector<int>& candidates, int index) {
        int sum = getSum(each);
        if (sum > target) {
            return;
        }
        if (sum == target) {
            result.push_back(each);
            return;
        }
        int n = candidates.size();
        for (int i = index; i < n; ++i) {
            each.push_back(candidates[i]);
            backTrace(target, candidates, i);
            each.pop_back();
        }
    }
    int getSum(vector<int> each) {
        int n = each.size();
        int sum = 0;
        for (int i = 0; i < n; ++i) {
            sum += each[i];
        }
        return sum;
    }
};

40 组合总和 II

本来以为很容易可以AC。。没想到题中的数组虽然不能一个数用多次,但有重复的数啊。。
be like:

题干
重复也不行
决定先排序再去重

unordered_set貌似没法去重vector<int>

看了下真的用哈希表去重很容易超时

题解:
可以看出添加了used数组专门用来记录同一层用过的重复元素

在这里插入图片描述

//
class Solution {
public:
    vector<vector<int>> result;
    vector<int> each;
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        sort(candidates.begin(), candidates.end());
        vector<bool> used(candidates.size(), false);
        backTrace(candidates, target, 0, used);
        return result;
    }
    void backTrace(vector<int>& candidates, int target, int index,
                   vector<bool>& used) {
        int sum = getSum(each);
        if (sum == target) {
            result.push_back(each);
            return;
        }
        if (sum > target) {
            return;
        }
        int n = candidates.size();
        for (int i = index; i < n; ++i) {
            if (i > 0 && candidates[i] == candidates[i - 1] &&
                used[i - 1] == false) {
                continue;
            }
            each.push_back(candidates[i]);
            used[i] = true;
            backTrace(candidates, target, i + 1, used);
            used[i] = false;
            each.pop_back();
        }
    }
    int getSum(vector<int> each) {
        int n = each.size();
        int sum = 0;
        for (int i = 0; i < n; ++i) {
            sum += each[i];
        }
        return sum;
    }
};

注意构造数组用法:vector<bool> used(candidates.size(), false);

剪枝:

for (int i = index; i < n && getSum(each)+candidates[i]<=target ; ++i) {

131 分割回文串

注意字符串反转函数,(algorithm中)
reverse(each.begin(), each.end())
注意
在主函数调用回溯函数之前先把两个全局变量清空(因为全局变量初始化之前没有赋值)

result.clear();
path.clear();

substr()写的有问题,第一位参数是起始位置,第二位是字符串长度(不是结束位置)

class Solution {
public:
    vector<string> each;
    vector<vector<string>> result;
    vector<vector<string>> partition(string s) {
        each.clear();
        result.clear();
        backTrace(s, 0);
        return result;
    }

    void backTrace(string s, int index) {
        int n = s.size();
        if (index >= n) {
            result.push_back(each);
            return;
        }
        for (int i = index; i < n; ++i) {
            string curr = s.substr(index, i -index + 1);
            if (isReverse(curr) == true) {
                each.push_back(curr);
                backTrace(s, i+1);
                each.pop_back();
            }
            
        }
        return;
    }
    bool isReverse(string each) {
        int n = each.size();
        int begin = 0;
        int end = n - 1;
        while (begin < end) {
            if (each[begin] != each[end]) {
                return false;
            }
            begin++;
            end--;
        }
        return true;
        // string curr = each;
        // reverse(curr.begin(),curr.end());
        // if(curr==each) return true;
        // return false;
    }
};

93.复原IP地址

跟上一题真的很类似但是不知道为什么第一版写的就是each存入不进result。。。感觉逻辑也没啥问题

class Solution {
public:
    vector<string> result;
    string each= "";
    vector<string> restoreIpAddresses(string s) {
        // result.clear();
        // each.clear();
        backTrace(s, 0);
        return result;
    }
    void backTrace(string s, int index){
        int n = s.size();
        if(each.size() > n+3){
            return;
        }//感觉不加也行,加了算是剪枝?
        if(index >= n ){
            if(each.size() == n+3){
                result.push_back(each);
            }
            return;
        }
        for(int i = index; i<n; ++i){
            string curr = s.substr(index, i-index+1);
            if(isValid(curr)==true){
                string save = each;
                each += '.';
                each += curr;
                backTrace(s, i+1);
                each.erase(each.begin() + i + 1);
            }
            else break;

        }
    }

    bool isValid(string curr){
        int n = curr.size();
        if(n==0 || n>3 ){
            return false;
        }
        if(n>1 && curr[0]=='0' ){
            return false;
        }
        int currNum =0;
        for(int i=n; i>=0;--i){
            if(curr[i] <'0' || curr[i] > '9'){
                return false;
            }
            currNum += (curr[i]-'0')*pow(10,n-i);
            if(currNum>255){
                return false;
            }
        }
        return true;
    }
};

清空重写
注意:
s.insert()
s.erase()

class Solution {
public:
    vector<string> result;
    vector<string> restoreIpAddresses(string s) {
        backTrace(s,0,0);
        return result;
    }
    void backTrace(string& s, int index, int pointSum){
        if(pointSum==3){
            string last = s.substr(index, s.size()-index);
            if(isValid(last)==true){
                result.push_back(s);
            }
            return;
        }
        for(int i = index; i<s.size(); ++i){
            string curr = s.substr(index, i-index+1);
            if(isValid(curr)==true){
                pointSum++;
                s.insert(s.begin()+i+1, '.');
                backTrace(s,i+2, pointSum);
                pointSum--;
                s.erase(s.begin()+i+1);
            }
            else{
                break;
            }
        }
    }

    bool isValid(string curr){
        int n = curr.size();
        if(n<=0 || n >3){
            return false;
        }
        if(n>1 && curr[0]=='0'){
            return false;
        }
        int sum = 0;
        int num = 1;
        for(int i = n-1 ; i>=0 ; --i){
            if(curr[i] < '0' || curr[i] > '9'){
                return false;
            }
            sum += (curr[i]-'0') * (num);
            num = num *10;
            if(sum > 255){
                return false;
            }
        }
        return true;
    }
};

AC

78.子集

普通回溯算法,巧思是有可能这一步啥也不选,因此在数组最后加一个0,如果index到最后一位了且当前为0,那么啥也不用push,直接回溯,也不用pop

class Solution {
public:
    vector<vector<int>> result;
    vector<int> each;
    vector<vector<int>> subsets(vector<int>& nums) {
        nums.push_back(0);
        backTrace(0,nums);
        return result;
    }
    void backTrace(int index, vector<int>& nums){
        int n = nums.size();
        if(index >=n){
            result.push_back(each);
            return;
        }
        for(int i = index ; i<n; ++i){
            if(i==n-1 && nums[i]==0){
                backTrace(i+1, nums);
                
            }
            else{
                each.push_back(nums[i]);
                backTrace(i+1, nums);
                each.pop_back();
            }
        }
    }
};

AC

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值