回溯算法之组合问题

1.回溯算法

回溯法也可以叫做回溯搜索法,它是一种搜索的方式。回溯是递归的副产品,只要有递归就会有回溯。

1.1题目分类

回溯算法主要解决组合、分割、子集、排列等问题。本博客将记录代码随想录回溯专题下的组合问题,用于日后的回忆与复习。

2.组合问题

组合问题通常用于求解一个集合中满足某个要求的子集了。

区别于排列问题,在组合问题中,给出集合{a,b}和{b,a},组合只关心组内元素不关心顺序,因此视为一个解。然而同一情况下,排列问题则视为两个解。

2.1问题描述

先从一个简单的小例子开始,给定五个不同颜色的小球,每种颜色的小球只能选取一次,如果两两配对组合,能够得到多少种组合。

图1.1

如图1.1所示,每一条黑线为一种组合方案。每次选取时,可选择的数目上限为给定集合的大小。当第一次选取到紫色后,第二次没有可选择的小球,因此舍去。

通过观察可以发现,进入下一层的选择后,选择空间变为上层选取结果的右侧小球。举例,第一次选择红球后,第二次选取的选择空间变为红球右侧(黄、蓝、绿、紫)。注意:由于限制每个小球只能选取一次,因此不能包括自己本身,如果没有这一限制,则红球也在第二次的选择空间内。图1.2直观展示这一过程。

图1.2

为什么会是这一结果呢?我们不妨假设第二次选取不受这样的限制。以图1.1中第一次选取黄色小球为例,倘若此时第二次选取了红球,此时组合的结果为{黄球,红球},这一组合方式不就与{红球,黄球}重复了嘛。因此我们需要一个标记,记录下一次选取时的开始位置。如果题目要求同一小球只能选取一次,那么下次选取的开始位置则为当前选取的位置+1。

2.2解题思路

回溯问题的思路可以抽象成一个树形结构,我们思考题目时可以将解题过程通过一颗N叉树体现出来。不同的题目要求只不过是细节上的差异。

3.算法题

3.1 组合
题目链接

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

示例: 输入: n = 4, k = 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]

题解一(不包含剪枝)

class Solution {

private:
    vector<vector<int>> result;
    vector<int> path;

    void backtracking(int n, int k, int startIndex)
    {
        if(path.size() == k)
        {
            result.push_back(path);
            return;
        }

        for(int i = startIndex; i <= n; i++)
        {
            path.push_back(i);
            backtracking(n, k, i + 1);
            path.pop_back();
        }


    }
public:
    vector<vector<int>> combine(int n, int k) 
    {
        path.clear();
        result.clear();
        backtracking(n, k, 1);
        return result;
    }
};

题解二(包含剪枝):

class Solution {
private:
    vector<vector<int>> result; //result
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值