递归(回溯)算法(24、25、37,39,40,46,45,47,77,,78,79,90,93)

递归三要素:

  1. 整个递归的终止条件。
  2. 一级递归需要做什么?
  3. 应该返回给上一级的返回值是什么?

1. 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

方法一:  直接用指针来调换节点位置

方法2:采用递归思想

  

2. 给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换

 * 相同类型题目  使用栈实现:核心在于依次取k个节点入栈,若满足数量要求,则移动指针,将栈内元素依次出栈 链在头结点后,并将这一部分最后元素与下一部分第一个节点相连。

*  难点在于:指针的变换 :首先,要有一个指针p接收出栈后的节点,即第一次进栈时此节点指向头结点不动,而后在出栈时用于接上每一个出栈的节点,并在最后与下一部分节点接上;然后需要一个指针tmp遍历K个节点,以此出栈,k个出栈后 最后落在k+1的节点上,并与p配合用于两部分相连。最后  要有一个head指针在进栈过程中 ,在tmp位置不动,在出现后续节点不足K个时,直接与p接上,返回为最终结果。

37 . 编写一个程序,通过填充空格来解决数独问题。数独的解法需 遵循如下规则:

  1. 数字 1-9 在每一行只能出现一次。
  2. 数字 1-9 在每一列只能出现一次。
  3. 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)

数独部分空格内已填入了数字,空白格用 '.' 表示。

思想: 递归 回溯法: 将矩阵内的已存在的数字按照每行、每列、小块先保存;在逐行遍历, 判断空白处要填入的数字(1-9)在这一空白所处的行、列、小块中有没有重复出现;若没有重复出现,填入;进入下一个空白处,依次递归

 39  组合总和1  :给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。 

思想: 递归   回溯算法;目标值target 挨个减去candidatas里的元素,若是结果为0的那一项,则为一种组合方式

回溯(dfs): 1.进行选择  2. 递归 3. 撤回选择 

在同一层,通过for 循环 开启同层所有符合要求的节点 往下进行,每一个节点往下   就是深度搜索dfs

46 全排列 :给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

思想: 回溯 递归   三步走(1.进行选择  2. 递归 3. 撤回选择  这里保证每一分支中,用过的数不在用的策略是  使用used  标记。(下题不同)

 

 首先  在dfs里写  终止条件;再写循环,循环里递归进行;在递归后,要撤回选择

40 .组合总和2 给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。candidates 中的每个数字在每个组合中只能使用 一次 。

注意:解集不能包含重复的组合。 

思想: 回溯递归:  每个组合中, candidates中每个元素只能使用一次;且解集不包含重复解

所以 1. 得采用used 或同类的方式 ,让每一分支向下时,不在使用  用过的元素;

        2.对于同层中值相同的节点,保留第一个 其他的跳过 ,以防产生重复解。

总结(39,40,46):可熟悉回溯算法 

*回溯三步走: 1.进行选择  2. 递归 3. 撤回选择 

*对于集合中的数字 在每组结果中只能使用一次:可使用 used 标记 或 采用 下标随着递归一直后移的方式。

*对于 不出现重复的解,可采用剪枝的方法,即剪去同层中值相同的节点,只保留一个。

对于撤回选择,是为保证  同层中  当前节点 递归对某些参数的标记、修改 不影响 后一节点,而只对当前节点的子节点   产生影响。

45. 跳跃游戏 II:给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]

每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i + j] 处:

  • 0 <= j <= nums[i] 
  • i + j < n

返回到达 nums[n - 1] 的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]

思想(方法一): 采用回溯算法。当前节点  +1,即为 跳 距离为1的一步,跳到当前当前值的最大值(没有过界的话)   结束条件是  下标到了数组长度的最后

47.全排列 II。全排列中  是输出所有排列组合。本题要求不能重复。

 思想:回溯,但要求剪枝;即在同层中剪去  和前一项 相同的节点分支

attention: 但剪枝要注意,不能剪去和上一节点值相同的子节点,   代码中的 not used[i-1] 即是用来区分 是与同层节点相同 ,还是 和父节点相同

51. N 皇后  :按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。

思路:回溯思想:  遍历每一行,找每一行中可放入皇后的位置,记录下来,遍历到最后行时,根据每一行的皇后位置,返回矩阵。

具体地:回溯思想,深度搜索。从第一行出发,确定同列、左上、右下无皇后,就是当前行可放皇后的位置,并记录

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

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

思想 :回溯算法  。要点在于  每个子节点 只取比其父节点大的值

代码思想: 第一层 循环从i=1 到n ,当等于i=1时, 里面递归  从i+1开始

79. 单词搜索  :给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

思想: 回溯递归算法:从 board 中的每一个位置出发,遍历上下左右,若board当前位置 与word[0] 不相等,则 从 board的下一个位置开始;若当前位置相同,则递归确定 board当前位置的下一位置 与word的下一位置相不相同,依次递归 。与之前的 dfs算法稍有不同

78. 子集

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

 

90. 子集 II

给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。

 

93. 复原 IP 地址

有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。

  • 例如:"0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址,但是 "0.011.255.245""192.168.1.312" 和 "192.168@1.1" 是 无效 IP 地址。

给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 '.' 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。

思想: 经典回溯算法。以sub取符合长度范围的切片,判断切片满不满足条件。满足条件:加入到ip里。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值