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

文章目录

1、组合

给定两个整数 n 和 k,返回范围 1, n 中所有可能的 k 个数的组合。

你可以按 任何顺序 返回答案。

cpp 复制代码
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 的不同 表达式 的数目。

cpp 复制代码
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 个。

cpp 复制代码
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 中的每个字母转变大小写,我们可以获得一个新的字符串。

返回 所有可能得到的字符串集合 。以 任意顺序 返回输出。

cpp 复制代码
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 开始),只要满足下述条件 之一 ,该数组就是一个 优美的排列 :

permi 能够被 i 整除

i 能够被 permi 整除

给你一个整数 n ,返回可以构造的 优美排列 的 数量 。

cpp 复制代码
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;
                }
            }
        }
    }
};
相关推荐
凯瑟琳.奥古斯特24 分钟前
力扣1008:前序重建BST
开发语言·c++·算法·leetcode·职场和发展
aqiu1111111 小时前
【算法日记 13】LeetCode 49. 字母异位词分组:哈希表的进阶“降维打击”
算法·leetcode·散列表
KaMeidebaby1 小时前
卡梅德生物技术快报|纳米抗体技术全套实操流程:AFB1 全合成文库淘选 + 分子对接定点突变参数手册
人工智能·python·tcp/ip·算法·机器学习
巴糖2 小时前
从做早餐理解 DAG 与拓扑排序:任务依赖图的核心逻辑
算法
2601_962851742 小时前
计算机毕业设计之基于YOLOV10的低光照目标检测算法研究与实现
大数据·算法·yolo·目标检测·信息可视化·cnn·课程设计
magicwt2 小时前
快手自动出价论文GAVE阅读笔记
算法
智者知已应修善业2 小时前
【P12159蓝桥杯数组翻转】2025-4-24
c语言·c++·经验分享·笔记·算法·蓝桥杯
小巧的砖头3 小时前
使用SVN+CruiseControl+ANT实现持续集成之一
学习·算法
人道领域3 小时前
【LeetCode刷题日记】贪心算法理论与实战:455.分发饼干最优解
java·开发语言·数据结构·算法·leetcode·贪心算法
小O的算法实验室4 小时前
2026年ACM TCH,动态救护车路径优化:结合 K-means 聚类与多目标粒子群算法两阶段策略
算法