回溯法 之 素数环

本文介绍了回溯法的概念,强调其试探性特点,并通过递归来理解其自动申请内存及退栈操作。作者通过图书搜索的例子展示了无控制遍历与剪枝效果的差异,指出回溯法如何减少时间和空间复杂度。最后,以素数环问题为例,阐述了如何应用回溯法解决问题。
摘要由CSDN通过智能技术生成

定义

根据我大百度的定义:
(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

个人的理解

回溯法的主要特点就是试探

试探 试探 试探(重要的话说三遍 = =,我好机智啊)

我们原来通过递归,其实就是不断的尝试,找到所有我们组合的结果,这种方法我们在全排列问题上经常见到。我们利用递归实质上就是不断利用系统栈进行数据的暂存(当然,这个系统栈和你使用的编程工具有关,他会自动的申请一定长度的系统栈(内存空间),申请系统栈的长度可以设置,但是一般情况下数据不会太长,否则会出现所谓“溢出”的情况,抽象理解就是数组被占满),以及满足一定情况下的”自动执行”系统退栈操作,来进行数据的填充,到达组合一定序列的目的。

可以看出递归的特点

  1. 自动申请内存地址连续内存空间,也就是我们数据结构课程中的栈结构,不必我们在编程的时候为数据暂存位置而担心。
  2. 当不满足一定条件后,我们的系统栈自动之后退栈操作,也就是把栈顶的数据进行Pop()操作(弹出数据),这个特性让我们进行数据组合填充的时候提供了足够方便的操作。

我们由此可知:回溯法在递归这两个特点的本身进行延伸,我们可以利用一定的条件加以限制,让我们尝试次数大大减少,实质是减少我们递归的次数和深度,即在一颗树上,在深度和广度两个空间上做出剪枝操作。

想象的场景

回溯法的控制
我们面前有一堆图书,有各种种类,比如会计类,金融类,文学类等等。现在给你一个任务就是在这堆图书中查找计算机类的图书。
当我们拿到第一本书,我们看到图书的外皮的书籍名称,比如《中国近代史》,已经把这本书的功能和

回溯法是一种解决问题的通用算法,可以用来解决许多组合优化问题,素数问题就是其中一种。下面是素数问题的伪代码以及代码设计过程: ## 素数问题伪代码 ```text function find_primes(n): primes = [] for i from 2 to n: if is_prime(i): primes.append(i) return primes function is_prime(n): if n < 2: return False for i from 2 to sqrt(n): if n % i == 0: return False return True function prime_ring(n): primes = find_primes(n) ring = [0] * n # 初始化 ring[0] = 1 # 确定第一个位置为1 used = [False] * n # 初始化已使用数组 used[0] = True # 第一个位置已使用 search(primes, ring, used, n, 1) # 从第二个位置开始搜索 function search(primes, ring, used, n, index): if index == n: # 如果找到一个解,则输出 if is_prime(ring[0] + ring[-1]): # 检查首尾是否相邻 print(ring) else: for i in range(1, n): if not used[i] and is_prime(primes[i] + ring[index - 1]): ring[index] = primes[i] # 将素数加入中 used[i] = True # 标记已使用 search(primes, ring, used, n, index + 1) # 继续搜索 used[i] = False # 回溯,标记为未使用 ``` ## 代码设计过程 素数问题的目标是在 $1$ 到 $n$ 之间找到一组数组成,使得相邻两个数之和为素数。首先我们需要找到 $1$ 到 $n$ 之间的所有素数,这可以通过一个 `find_primes` 函数来完成。这个函数会遍历 $2$ 到 $n$ 之间的所有数,检查它们是否为素数,并将素数存储在一个列表中返回。 接下来,我们需要一个函数来判断一个数是否为素数,这可以通过一个 `is_prime` 函数来完成。这个函数会遍历 $2$ 到 $\sqrt{n}$ 之间的所有数,检查它们是否为 $n$ 的因子。如果找到了一个因子,那么 $n$ 不是素数,否则 $n$ 是素数。 有了素数列表之后,我们可以开始搜索素数。我们需要一个长度为 $n$ 的数组来存储中的素数,并且需要一个与之对应的布尔数组来记录哪些素数已经被使用过了。我们首先将第一个位置设置为 $1$,因为是循的,所以第一个位置的值没有影响。接下来,我们从第二个位置开始搜索,对于每个位置,我们需要遍历素数列表,找到一个没有被使用的素数,使得它和前一个位置的素数之和为素数。如果找到了这样的素数,我们将它加入中,标记为已使用,然后递归搜索下一个位置。如果在某个位置上找不到合适的素数,则回溯到上一个位置,并且把该位置的素数标记为未使用。 最后,如果找到了一个完整的素数,我们还需要检查第一个素数和最后一个素数之和是否为素数。如果是素数,则输出这个
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值