backtrack

[LeetCode] Backtracking Template for (Subsets, Permutations, and Combination Sum)

大兔子大兔子 提交于 2021-02-14 21:04:28
根据 issac3 用Java总结了backtracking template, 我用他的方法改成了Python. 以下为template. 1 def backtrack(ans, temp, nums, start): # 可能有start, 也可能没有 2 if len(temp) == len(nums): 3 ans.append(temp) 4 else : 5 for i in range(start, len(nums)): 6 if nums[i] not in temp: 7 backtrack(ans, temp + [nums[i]], nums, i + 1) # 如果可以重复利用同一个元素,那么 用 i 8 9 ans = [] 10 nums.sort() # 可能需要sort 11 backtrack(ans, [], nums, 0) 12 return ans 可以用来解决的问题有: Leetcode 78. Subsets , Leetcode 90. Subsets II, Leetcode 46. Permutations, Leetcode 47. Permutations II(contains duplicates), Leetcode 39. Combination Sum, Leetcode 40. Combination Sum

回溯法

蓝咒 提交于 2021-02-12 12:02:01
回溯法实例详解(转) 概念 回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。 回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。 许多复杂的,规模较大的问题都可以使用回溯法,有“通用解题方法”的美称。 基本思想 在包含问题的所有解的解空间树中,按照 深度优先搜索的策略 ,从根结点出发深度探索解空间树。当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。(其实回溯法就是对隐式图的深度优先搜索算法)。 若用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。 而若使用回溯法求任一个解时,只要搜索到问题的一个解就可以结束。 解题步骤  (1)针对所给问题,确定问题的解空间: 首先应明确定义问题的解空间,问题的解空间应至少包含问题的一个(最优)解。 (2)确定结点的扩展搜索规则 (3)以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索 子集树,排列数及其他   子集树概念:当所给问题是从n个元素的集合S中

算法分析与设计-回溯法

末鹿安然 提交于 2021-01-28 07:32:21
一、0/1 Knapsack Problem 1、实验题目 运用回溯法实现实验3中的0/1背包问题 2、使用的算法 回溯法 3、算法分析与设计 利用回溯法试设计一个算法求出0-1背包问题的解,也就是求出一个解向量xi (即对n个物品放或不放的一种的方案) 其中, (xi = 0 或1,xi = 0表示物体i不放入背包,xi =1表示把物体i放入背包)。在递归函数Backtrack中: 当i>n时,算法搜索至叶子结点,得到一个新的物品装包方案。此时算法适时更新当前的最优价值。     当i<n时,当前扩展结点位于排列树的第(i-1)层,此时算法选择下一个要安排的物品,以深度优先方式递归的对相应的子树进行搜索,对不满足上界约束的结点,则剪去相应的子树。 4、项目测试(功能与性能) 因为物品只有选与不选2个决策,而总共有n个物品,所以时间复杂度为O(2^n)。因为递归栈最多达到n层,而且存储所有物品的信息也只需要常数个一维数组,所以最终的空间复杂度为O(n)。 5、实验总结 0/1背包属于找最优解问题,用回溯法需要构造解的子集树。对于每一个物品i,对于该物品只有选与不选2个决策,总共有n个物品,可以顺序依次考虑每个物品,这样就形成了一棵解空间树:基本思想就是遍历这棵树,以枚举所有情况,最后进行判断,如果重量不超过背包容量,且价值最大的话,该方案就是最后的答案。 二、8-Queen

初识渗透测试

时光怂恿深爱的人放手 提交于 2021-01-27 02:39:00
前 言 熟悉军事的朋友都应该了解,各个国家的军队每年都会组织一些军事演习来检验部 队的攻防战术和作战能力,在美国,一般会将美军称为蓝军,将假想敌称为红军,这种军事演戏的方式,也在上个世纪90年代引入美军的网络安全和信息基础设施的实际攻防测试过程。由 一群接受过 职业培训的安全专家作为红方,对防御方蓝方进行安全攻击,以实战的方式来检验目标系统的防御体系和应急响应计划的有效性,这种通过实际的攻击方式进行安全测试和评估的方法就是安全渗透测试。 在20世纪90年代后期,逐步开始从军队和情报部门拓展到安全界,一些对安全需求很高的企业开始采用这种方式来对他们的网络和系统进行测试 。 一 、渗透测试概述 所谓渗透测试是借助各种漏洞扫描工具,通过模拟黑客的攻击方 法来对网络安全进行评估。 渗透测试类型 选择的渗透测试类型取决于公司和组织的用途和范围 - 他们是否想要模拟员工,网络管理员或外部来源的攻击。通常,有三种不同类型的渗透测试: 黑盒测试 : 是指对基础设施不知情的情况下进行测试。黑盒测试比较费时费力,同时要求渗透测试者具备较高的技术能力; 白盒测试: 是指在完全了解结构的情况下进行的测试。白盒测试能比黑盒测试消除更多的目标的安全漏洞,给客户带来更大的价值。白盒测试最大的问题在于无法有效的测试客户的应急响应程序,无法判断客户的安全防护计划对检测特定的统计的效率; 灰盒测试 :

聊聊算法——回溯算法

狂风中的少年 提交于 2020-10-09 00:30:11
“递归只应天上有,迭代还须在人间”,从这句话我们可以看出递归的精妙,确实厉害,递归是将问题规模逐渐减小, 然后再反推回去,但本质上是从最小的规模开始,直到目标值,思想就是数学归纳法,举个例子,求阶乘 N!=(N-1)!*N , 而迭代是数学中的极限思想,利用前次的结果,逐渐靠近目标值,迭代的过程中规模不变,举例如For循环,直到终止条件。 递归的思想不复杂,但代码理解就麻烦了,要理解一个斐波那契数组递归也不难,比如下面的回溯算法递归,for 循环里面 带递归,看代码是不是晕了?好,下面我们专门来聊聊这个框架! 作者原创文章,谢绝一切形式转载,违者必究! 准备: Idea2019.03/JDK11.0.4 难度: 新手-- 战士 --老兵--大师 目标: 回溯算法分析与应用 1 回溯算法 先给出个回溯算法框架: backtrack(路径,选择列表){ // 结束条件 将中间结果加入结果集 for 选择 in 选择列表: // 做选择,并将该选择从选择列表中移除 路径.add(选择) backtrack(路径,选择列表) // 撤销选择 路径.remove(选择) } 为了理解上述算法,回想一下,我前篇文章中有说到,多路树的遍历算法框架: private static class Node { public int value; public Node[] children; }

力扣-46. 全排列

纵饮孤独 提交于 2020-09-29 07:59:41
0. 题目 1.飞哥的题解 class Solution { public List<List<Integer>> permute(int[] nums) { List<Integer> numList = new ArrayList<>(); for (int i = 0; i < nums.length; i++) { numList.add(nums[i]); } List<List<Integer>> resultList = new ArrayList<>(); List<Integer> rightList = new ArrayList<>(); find(resultList, rightList, numList); return resultList; } private void find(List<List<Integer>> resultList, List<Integer> rightList, List<Integer> numList) { for (int i = 0; i < numList.size(); i++) { Integer number = numList.remove(i); rightList.add(number); if (numList.isEmpty()) { resultList.add(new ArrayList<>

全面解析回溯法:算法框架与问题求解

时光怂恿深爱的人放手 提交于 2020-08-13 02:12:24
目录 什么是回溯法? 回溯法的通用框架 利用回溯法解决问题 问题1:求一个集合的所有子集 问题2:输出不重复数字的全排列 问题3:求解数独——剪枝的示范 问题4:给定字符串,生成其字母的全排列 问题5:求一个n元集合的k元子集 问题6:电话号码生成字符串 问题7:一摞烙饼的排序 问题8:8皇后问题 总结与探讨 附:《算法设计手册》第7章其余面试题解答    摘了一段来自百度百科对回溯法思想的描述: 在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深度探索解空间树。当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。(其实回溯法就是对隐式图的深度优先搜索算法)。 若用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。 而若使用回溯法求任一个解时,只要搜索到问题的一个解就可以结束。   可以把回溯法看成是递归调用的一种特殊形式。其实对于一个并非编程新手的人来说,从来没使用过回溯法来解决问题的情况是很少见的,不过往往是“对症下药”,针对特定的问题进行解答。这些天看了《算法设计手册》回溯法相关内容,觉得对回溯法抽象的很好。如果说算法是解决问题步骤的抽象,那么这个回溯法的框架就是对大量回溯法算法的抽象。本文将对这个回溯法框架进行分析

NFA到DFA的转换

*爱你&永不变心* 提交于 2020-08-07 04:04:06
一、有限自动机 1、不确定的有限自动机(NFA) 只要有一条路径能够使一个字符串从初始态到达接收态就称这个字符串是接收的 匹配结果,是不确定的 慢,有Backtrack(回溯) 基于表达式 某时刻可能处于一组状态之中的任何一个,因此记录所有的可能路径 2、确定的有限自动机(DFA) 匹配速度,是确定的 快,无Backtrack(回溯) 基于文本 在任意时刻必定处于某个确定状态 二、NFA到DFA转换 1、根据RE构造NFA 2、NFA转为DFA 又称 NFA的确定化 状态转换表 注:标有*为接收状态 带 ε 边记得增加一列 NFA的开始状态集合为[0],将NFA将接收的符号代入当前状态, 最长子串原则 ,得出新产生的状态 将 新产生的状态作为将来要列出的状态 重复1中步骤 直至 新产生的状态集合中无新集合 时结束 将第一列中将来要列的状态 重命名 转换为DFA S 0 为初始状态,根据状态转换表中 NFA接受的符号 产生的集合 到重命名中寻找匹配的状态 画图,根据新的圈重复1中步骤,直至结束 重命名中标有*的接受态要用双圈标出 计算 ε -closure(T): 来源: oschina 链接: https://my.oschina.net/u/4267459/blog/4299598

leetcode 784. Letter Case Permutation——所有BFS和DFS的题目本质上都可以抽象为tree,这样方便你写代码

孤街浪徒 提交于 2020-05-02 12:44:34
Given a string S, we can transform every letter individually to be lowercase or uppercase to create another string. Return a list of all possible strings we could create. Examples: Input: S = "a1b2" Output: ["a1b2", "a1B2", "A1b2", "A1B2"] Input: S = "3z4" Output: ["3z4", "3Z4"] Input: S = "12345" Output: ["12345"] Note: S will be a string with length at most 12 . S will consist only of letters or digits. 本质上是排列问题,经典的dfs求解。将字符串看作一棵树,dfs遍历过程中修改node为大写或者小写字母即可! 解法1: class Solution { public: vector <string> letterCasePermutation(string S) { // A! use DFS vector <string> ans; dfs(ans, S, 0);

每日一题-——LeetCode(46)全排列

谁说我不能喝 提交于 2020-04-28 07:05:27
题目描述: 给定一个没有重复数字的序列,返回其所有可能的全排列。 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ] import itertools class Solution: def permute(self, nums): res = [] def backtrack(nums, tmp): if not nums: res.append(tmp) return for i in range(len(nums)): backtrack(nums[:i] + nums[i+1:], tmp + [nums[i]]) backtrack(nums, []) return res def permute2(self,nums): return list(itertools.permutations(nums)) LeetCode(47)全排列2 题目描述: 给定一个可包含重复数字的序列,返回所有不重复的全排列。 输入: [1,1,2] 输出: [ [1,1,2], [1,2,1], [2,1,1] ] class Solution: def permuteUnique(self, nums): res = [] def backtrack(nums, tmp): if not nums