day24|回溯算法1-基础&组合

回溯法基础知识准备

回溯定义

递归和回溯的区别: 递归回溯相辅相成,递归函数下边的部分即为回溯的逻辑。
回溯搜索法:纯暴力搜索法,有些问题利用暴力搜索法搜不出来,需要使用回溯法进行搜索。

  1. 组合问题:N个数里面按一定规则找出k个数的集合
  2. 切割问题:一个字符串按一定规则有几种切割方式
  3. 子集问题:一个N个数的集合里有多少符合条件的子集
  4. 排列问题:N个数按一定规则全排列,有几种排列方式
  5. 棋盘问题:N皇后,解数独等等
    这些问题利用一般的for循环是比较难解决的,而使用回溯法可以很好的解决这些问题。

如何理解回溯法

在这里插入图片描述

回溯法都可以抽象为一个树形结构,横向使用for循环,纵向使用递归的方式。

回溯法C++伪代码模板

void backtracking(){
	if(终止条件){
		收集结果,将叶子结点的数值收集到结果集中
		return
	}
	// 单层搜索,for循环对应所有子节点的个数,用来处理相应的结点。
	for(集合的元素集){
		处理结点
		递归函数
		撤销结点
	}
	return
	}

77 组合

在这里插入图片描述
题目描述: 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。
在这里插入图片描述
C++伪代码(如何按照上述的结构,将回溯问题进行求解)

//确定递归函数的参数和返回值,一个组合是一个一维数组,将组合进行存放,因而需要将一维数组进行存放
//确定递归的终止条件
//确定单层递归的逻辑
//将组合问题的结构进行实现
二维数组result //全局变量
一维数组path
void backtracking(n,k,startIndex){
// 数组的长度,组合的长度,最后再传入本次要搜索的起始位置。
	if(path.size==k){
		result.push(path)
		return //不需要返回值的话,在终止条件中直接返回return即可
	}
	// 单层搜索的过程
	for(i=startIndex,i<=n,i++){
		path.push(i)
		backtracking(n,k,startIndex+1)
		path.pop(i) // 将之前的元素进行弹出
	}
}
class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        # 组合问题的求解
        result = []
        path = []
        def backtracking(k,startIndex):
            if len(path) == k:
                result.append(path.copy())
                return 
            # 回溯法的思路:首先遍历所有的叶子结点,然后再利用相同的方式进行遍历,回溯完成之后将上一步的结果回归的原始状态,确定终止条件,如果题目中没有返回值那么终止条件中直接写return即可。
            for i in range(startIndex,n+1): 
                path.append(i)
                backtracking(k,i+1)
                path.pop()
        backtracking(k,1)
        return result

注意: 追加path的结果时,需要进行数组的拷贝,否则最终结果会由于数组只是引用了地址,造成最终的结果发生改变。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值