回溯算法——组合问题

39. 组合总和

力扣题目链接(opens new window)

给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的数字可以无限制重复被选取。

说明:

  • 所有数字(包括 target)都是正整数。

  • 解集不能包含重复的组合。

示例 1:

  • 输入:candidates = [2,3,6,7], target = 7,

  • 所求解集为: [ [7], [2,2,3] ]

示例 2:

  • 输入:candidates = [2,3,5], target = 8,

  • 所求解集为: [ [2,2,2,2], [2,3,3], [3,5] ]

代码随想录的方法:

#include<bits/stdc++.h>
using namespace std;
vector<vector<int> > result;        //注意最后两个> >之间要加上空格 
vector<int> path;
void backtracking(int sum, int candidates[],int target,int startIndex)
{
    if(sum > target) return ; 
    if(sum==target){
        result.push_back(path);
        return;
    }
    
    for(int i=startIndex ; i < 3 ; i++)
    {
        sum += candidates[i];
        path.push_back(candidates[i]);
        backtracking(sum,candidates,target,i);
        sum -= candidates[i];
        path.pop_back();
    }
        
}
int main()
{
    int candidates[3]={2,3,5};
    int target = 8;
    backtracking(0,candidates,target,0);
    for(int i=0;i<result.size();i++){
      vector<int> cmp = result[i];
      for(int j = 0; j< cmp.size(); j ++){
        cout<<cmp[j]<<" ";
      }
      cout<<endl;
    }
} 

赵*磊教的方法:

#include<bits/stdc++.h>
using namespace std;
vector<vector<int> > result;        //注意最后两个> >之间要加上空格 
vector<int> path;
int candidates[3]={2,3,5};
int target = 8;

void dfs(int sum, int now){
    if(sum > target) return;
    if(sum == target){
        result.push_back(path);
        return;
    }
    for(int i = now; i < 3; i ++){
        path.push_back(candidates[i]);
        dfs(sum+candidates[i], i);
        path.pop_back();
    }
}

int main()
{
    dfs(0, 0);
    for(int i=0;i<result.size();i++){
          vector<int> cmp = result[i];
          for(int j = 0; j< cmp.size(); j ++){
            cout<<cmp[j]<<" ";
          }
          cout << endl;
      }
} 

如果每个数只能取一次:

//只能取一个数 
#include<bits/stdc++.h>
using namespace std;
vector<vector<int> > result;        //注意最后两个> >之间要加上空格 
vector<int> path;
int candidates[3]={2,3,5};
int target = 8;
void dfs(int now, int sum){
    if(sum == target){
        result.push_back(path);
        return;
        }
    if(now >= 3) return;
    if(sum == target){
        result.push_back(path);
        return;
    }
    dfs(now+1, sum);
    path.push_back(candidates[now]);
    dfs(now+1, sum+candidates[now]);
    path.pop_back();
}

int main()
{
    dfs(0, 0);
    for(int i=0;i<result.size();i++){
      vector<int> cmp = result[i];
      for(int j = 0; j< cmp.size(); j ++){
        cout<<cmp[j]<<" ";
      }
  }
} 

93.复原IP地址

力扣题目链接(opens new window)

给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。

有效的 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。

例如:"0.1.2.201" 和 "192.168.1.1" 是 有效的 IP 地址,但是 "0.011.255.245"、"192.168.1.312" 和 "192.168@1.1" 是 无效的 IP 地址。

示例 1:

  • 输入:s = "25525511135"

  • 输出:["255.255.11.135","255.255.111.35"]

#include<bits/stdc++.h>
using namespace std;
string arr="25525511135"; 
vector<string> result; 
bool check( string arr, int start ,int end)
{
    if (arr[start]=='0' && start!= end) { // 0开头的数字不合法
                return false;
    }
    if (start > end) {
            return false;
    }    
    int sum = 0;
    for(int i=start ; i <= end ; i++){
        sum = sum*10+(arr[i] - '0');
        if(sum>255){
            return false;
        }
    }
    return true;
}
void backtracking(string arr,int startIndex,int count)
// startIndex: 搜索的起始位置        count :添加逗点的数量
{
    if(count == 3){            // 逗点数量为3时,分隔结束
    // 判断第四段子字符串是否合法,如果合法就放进result中
        if(check(arr,startIndex,arr.size()-1)){
            result.push_back(arr);
        }
        return; 
    }
    for(int i = startIndex ;i < 11 ; i++)
    {
        if(check(arr,startIndex,i)){        // 判断 [startIndex,i] 这个区间的子串是否合法
            arr.insert(arr.begin() + i + 1 , '.');                // 在i的后面插入一个逗点
            count++;
            backtracking(arr, i+2 ,count);
            // 回溯
            count--;    
            arr.erase(arr.begin()+i+1);        // 回溯删掉逗点
        }else{
            break;            // 不合法,直接结束本层循环
        }
    }
}
int main()
{
    backtracking(arr,0,0);
    
    for(int i=0; i < result.size() ; i++){
        cout<<result[i]<<endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值