【刷题篇】回溯算法(四)

发布于:2024-04-19 ⋅ 阅读:(21) ⋅ 点赞:(0)

1、组合

给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。
你可以按 任何顺序 返回答案。

在这里插入图片描述

class Solution {
public:
    vector<vector<int>> ret;
    int n,k;
    vector<int> path;
    vector<vector<int>> combine(int _n, int _k) {
        n=_n;
        k=_k;
        dfs(1);
        return ret;
        
    }
    void dfs(int begin)
    {
        if(path.size()==k)
        {
            ret.push_back(path);
            return ;
        }
        for(int i=begin;i<=n;i++)
        {
            path.push_back(i);
            dfs(i+1);
            path.pop_back();//恢复现场
        }     
    }
};

2、目标和

给你一个非负整数数组 nums 和一个整数 target 。
向数组中的每个整数前添加 ‘+’ 或 ‘-’ ,然后串联起所有整数,可以构造一个 表达式 :
例如,nums = [2, 1] ,可以在 2 之前添加 ‘+’ ,在 1 之前添加 ‘-’ ,然后串联起来得到表达式 “+2-1” 。
返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。

在这里插入图片描述

class Solution {
public:
    int aim;
    int ret=0;
    int findTargetSumWays(vector<int>& nums, int target) {
        aim=target;
        dfs(nums,0,0);
        return ret;   
    }
    void dfs(vector<int> &nums,int pos,int target)
    {
        if(pos==nums.size())
        {
            if(target==aim) ret++;
            return ;
        }
        
        dfs(nums,pos+1,target+nums[pos]);

        dfs(nums,pos+1,target-nums[pos]);
    }
};

3、组合总和

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target 的不同组合数少于 150 个。
在这里插入图片描述

class Solution {
public:
    vector<vector<int>> ret;
    vector<int> path;
    //int sum;
    int target;
    vector<vector<int>> combinationSum(vector<int>& candidates, int _target) {
        target=_target;
        dfs(candidates,0,0);
        return ret;
    }

    void dfs(vector<int>& candidates,int begin,int sum)
    {
        if(sum==target)
        {
            ret.push_back(path);
            return ;
        }
        else if(sum>target)
            return ;
        //方法一
        // for(int i=begin;i<candidates.size();i++)
        // {
        //     path.push_back(candidates[i]);
        //     //sum+=candidates[i];
        //     dfs(candidates,i,sum+candidates[i]);
        //     path.pop_back();
        //     //sum-=candidates[i];
        // }
        //方法二
        for(int k=0;k*candidates[begin]+sum<=target;k++)
        {
            if(k) path.push_back(candidates[begin]);
            dfs(candidates,begin+1,sum+k*candidates[begin]);
        }

        for(int k=1;k*candidates[begin]+sum<=target;k++)
        {
            path.pop_back();
        }
    }
};

4、字母大小写全排列

给定一个字符串 s ,通过将字符串 s 中的每个字母转变大小写,我们可以获得一个新的字符串。
返回 所有可能得到的字符串集合 。以 任意顺序 返回输出。
在这里插入图片描述

class Solution {
public:
    string path;
    vector<string> ret;
    int n;

    char change(char ch)
    {
        if(ch>='a'&&ch<='z') ch-=32;
        else ch+=32;
        return ch;  
    }
    
    vector<string> letterCasePermutation(string s) {
        n=s.size();
        dfs(s,0);
        return ret;
    }
    void dfs(string &s,int pos)
    {
        if(pos==n)
        {
            ret.push_back(path);
            return ;
        }
        char ch=s[pos];
        //不改变
        path.push_back(s[pos]);
        dfs(s,pos+1);
        path.pop_back();

        if(ch<'0'||ch>'9')
        {
            char tmp=change(ch);
            path.push_back(tmp);
            dfs(s,pos+1);
            path.pop_back();
        }
    }
};

5、优美的排列

假设有从 1 到 n 的 n 个整数。用这些整数构造一个数组 perm(下标从 1 开始),只要满足下述条件 之一 ,该数组就是一个 优美的排列 :
perm[i] 能够被 i 整除
i 能够被 perm[i] 整除
给你一个整数 n ,返回可以构造的 优美排列 的 数量 。
在这里插入图片描述

class Solution {
public:
    bool check[16];
    int sum=0;
    int countArrangement(int n) {
        dfs(n,1);
        return sum;
    }

    void dfs(int n,int pos)
    {
        if(n+1==pos)
        {
            sum++;
            return ;
        }
        for(int i=1;i<=n;i++)
        {
            if(pos%i==0||i%pos==0)
            {
                if(check[i]==false)
                {
                    check[i]=true;
                    dfs(n,pos+1);
                    check[i]=false;
                }
            }
        }
    }
};