回溯算法

组合总数--回溯+剪枝

泄露秘密 提交于 2020-04-05 18:19:02
组合总和。 给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 例: candidates = [2,3,6,7], target = 7, [ [7], [2,2,3] ] candidates = [2,3,5], target = 8, [ [2,2,2,2], [2,3,3], [3,5] ] 回溯算法框架: rs=[] def backtrack(路径,选择列表): if 满足结束条件: rs.add(路径) return for 选择 in 选择列表: 做选择 backtrack(路径,选择列表) 撤销选择 全排列模板:permutation p(n,d) p(nums,d,n,used,curr,ans): if d==n: ans.append(curr); return for i=0 to len(nums): if used[i]:continue used[i]=True curr.push(nums[i]) p(nums,d+1,n,curr,ans) curr.pop() used[i]=False 组合模板:--特点,后面的数都比前面的数大!--不重复(所以递归为i+1);可以重复(递归为i) combination c(n,d) c(nums,d,n

回溯算法----单词搜索

此生再无相见时 提交于 2020-04-02 10:20:48
给定一个二维网格和一个单词,找出该单词是否存在于网格中。 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。 示例: board = [ ['A','B','C','E'], ['S','F','C','S'], ['A','D','E','E'] ] 给定 word = "ABCCED", 返回 true 给定 word = "SEE", 返回 true 给定 word = "ABCB", 返回 false 提示: board 和 word 中只包含大写和小写英文字母。 1 <= board.length <= 200 1 <= board[i].length <= 200 1 <= word.length <= 10^3 解答(C++): class Solution { public: bool en; bool backTrace(vector<vector<char>>& board, int i, int j, string& word, int index) { if (board[i][j] != word[index]) return false; if (index == word.size() -1) return true; char tmp = board[i][j

动态规划、回溯、贪心,分治

帅比萌擦擦* 提交于 2020-03-17 01:24:09
某厂面试归来,发现自己落伍了!>>> 动态规划篇 从斐波那契数列开始 我们先给出斐波那契数列的常用算法类 public class Fibonacci { private static int num = 0 ; private Fibonacci () { } public static int fib ( int n) { num ++ ; if (n == 0 ) { return 0 ; } if (n == 1 ) { return 1 ; } return fib (n - 1 ) + fib (n - 2 ) ; } public static void main (String[] args) { num = 0 ; int n = 20 ; long start = System. nanoTime () ; int res = Fibonacci. fib (n) ; long end = System. nanoTime () ; System. out .println(res) ; System. out .println((end - start) / 1000000000.0 ) ; System. out .println( num ) ; } } 运行结果 6765 3.96599E-4 21891 此时我们调大n的值为40 运行结果

把回溯理一下

喜你入骨 提交于 2020-03-05 18:24:31
趁着这个题目把回溯算法理了一下。 看了一个博客写的很详细: https://segmentfault.com/a/1190000018319044 对于这道题,同样可以将输出的排列方式转化为n个解空间的解,n为输入串的数字个数。 关键在于,求出某一组解result=[s1,s2,s3,....sn]后,要回退到该组解的上一个状态,即result=[s1,s2,s3,....sn-1],并在该状态求出下一组解。所以在这道题的实现中,方法为将result保存在结果中,回溯到上一个状态后将最后一个字符去掉以达到回退到改组解上一个状态的目的。 对于回溯,递归是再合适不过了。 贴上代码: class Solution { public: vector<string> alpha = {"abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"}; vector<string> letterCombinations(string digits) { if(!digits.length()) return {}; int n = digits.length(); vector<string> result; string tmp; backtrace(0,digits,tmp,result); return result; } void backtrace

算法思想

你说的曾经没有我的故事 提交于 2020-03-03 09:34:52
1.算法思想的概念 ================================================================================================ 1.1贪心--贪心思想 ======================================================================================================= 1.1.1 贪心--背包问题 ========================================================================================================================= 1.1.2 贪心--贪心算法思考 ======================================================================================================== 1.2、贪心-贪心算法应用场景 ======================================================================================================

字符串模式匹配KMP算法

拥有回忆 提交于 2020-02-21 17:02:10
字符串模式匹配指的是,找出特定的模式串在一个较长的字符串中出现的位置。 朴素的模式匹配算法 很直观的可以写出下面的代码,来找出模式串在一个长字符串中出现的位置。 1: /* 2: 朴素的模式匹配算法 3: 功能:字符串的模式匹配 4: 参数: 5: s:目标串 6: p:模式串 7: pos:开发匹配的位置 8: 返回值: 9: 匹配成功,返回模式串在目标串的其实位置 10: 匹配不成功,返回-1 11: */ 12: int match(const char * s ,const char * p,int pos){ 13: int i = pos ; 14: int j= 0 ; 15: while(s[i] != '\0' && p[j] != '\0') { 16: if(s[i] == p[j]) { 17: i ++ ; 18: j ++ ; 19: }else { 20: i = i - j + 1; 21: j = 0 ; 22: } 23: } 24: 25: if(p[j] == '\0') 26: return i - j ; 27: else 28: return -1 ; 29: } 上面的代码,s就是目标串,p是模式串,pos指定从s的什么位置开始匹配p。其实现思想也很简单: 当s[i] == p[j]时,目标串和模式串的指针都向后移动一位,进行匹配

深度好文:回溯算法详解

坚强是说给别人听的谎言 提交于 2020-02-17 10:28:53
这篇文章是很久之前的一篇《回溯算法详解》的进阶版,之前那篇不够清楚,就不必看了,看这篇就行。把框架给你讲清楚,你会发现回溯算法问题都是一个套路。 废话不多说,直接上回溯算法框架。 解决一个回溯问题,实际上就是一个决策树的遍历过程 。你只需要思考 3 个问题: 1、路径:也就是已经做出的选择。 2、选择列表:也就是你当前可以做的选择。 3、结束条件:也就是到达决策树底层,无法再做选择的条件。 如果你不理解这三个词语的解释,没关系,我们后面会用「全排列」和「N 皇后问题」这两个经典的回溯算法问题来帮你理解这些词语是什么意思,现在你先留着印象。 代码方面,回溯算法的框架: result = [] def backtrack(路径, 选择列表): if 满足结束条件: result.add(路径) return for 选择 in 选择列表: 做选择 backtrack(路径, 选择列表) 撤销选择 其核心就是 for 循环里面的递归,在递归调用之前「做选择」,在递归调用之后「撤销选择」 ,特别简单。 什么叫做选择和撤销选择呢,这个框架的底层原理是什么呢?下面我们就通过「全排列」这个问题来解开之前的疑惑,详细探究一下其中的奥妙! 一、全排列问题 我们在高中的时候就做过排列组合的数学题,我们也知道 n 个不重复的数,全排列共有 n! 个。 PS: 为了简单清晰起见

kmp算法总结

安稳与你 提交于 2020-02-15 05:44:12
转载分享,是我看到的最好懂的kmp讲解了!!谢谢原作,贴上链接 原作链接 KMP算法 KMP算法是一种线性时间复杂度的字符串匹配算法,它是对BF(Brute-Force,最基本的字符串匹配算法)的改进。对于给定的原始串S和模式串T,需要从字符串S中找到字符串T出现的位置的索引。KMP算法由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此人们称它为Knuth–Morris–Pratt算法,简称KMP算法。在讲解KMP算法之前,有必要对它的前身–BF算法有所了解,因此首先将介绍最朴素的BF算法。 一:BF算法简介 如上图所示,原始串S=abcabcabdabba,模式串为abcabd。(下标从0开始)从s[0]开始依次比较S[i] 和T[i]是否相等,直到T[5]时发现不相等,这时候说明发生了失配,在BF算法中,发生失配时,T必须回溯到最开始,S下标+1,然后继续匹配,如下图所示: 这次立即发生了失配,所以继续回溯,直到S开始下表增加到3,匹配成功。 容易得到,BF算法的时间复杂度是O(n*m)的,其中n为原始串的长度,m为模式串的长度。BF的代码实现也非常简单直观,这里不给出,因为下一个介绍的KMP算法是BF算法的改进,其时间复杂度为线性O(n+m),算法实现也不比BF算法难多少。 二:KMP算法 前面提到了朴素匹配算法,它的优点就是简单明了

Java实现搜索回溯经典题目

ぐ巨炮叔叔 提交于 2020-02-13 15:28:13
前言 搜索与回溯是计算机解题中常用的算法,很多问题无法根据某种确定的计算法则来求解,可以利用搜索与回溯的技术求解。回溯是搜索算法中的一种控制策略。它的基本思想是:为了求得问题的解,先选择某一种可能情况向前探索,在探索过程中,一旦发现原来的选择是错误的,就退回一步重新选择,继续向前探索,如此反复进行,直至得到解或证明无解。 如迷宫问题:进入迷宫后,先随意选择一个前进方向,一步步向前试探前进,如果碰到死胡同,说明前进方向已无路可走,这时,首先看其它方向是否还有路可走,如果有路可走,则沿该方向再向前试探;如果已无路可走,则返回一步,再看其它方向是否还有路可走;如果有路可走,则沿该方向再向前试探。按此原则不断搜索回溯再搜索,直到找到新的出路或从原路返回入口处无解为止。 搜索框架 搜索伪代码/公式 基本上所有的搜索与回溯都是这个公式的变种 void Search ( int k ) {   for ( i = 1 ; i <= 算符种数 ; i ++ )    if ( 满足条件 )    {     保存结果      if ( 到目的地 ) 输出解 ;     else Search ( k + 1 ) ;     恢复:保存结果之前的状态 { 回溯一步 }     } } 经典问题 【问题1】八皇后问题 题目 八皇后问题:要在国际象棋棋盘中放八个皇后,使任意两个皇后都不能互相吃。(提示

回溯算法 - 子集和问题

前提是你 提交于 2020-02-13 11:03:28
(1)问题描述:子集和问题的一个实例为<data, num>。其中 data = {x 1 , x 2 , ......, x n } 是一个正整数的集合,targetValue 是一个正整数。子集和问题判定是否存在 data 的一个子集 data1,使得 x 1 + x 2 + ...... + x n = targetValue (x € data1) (2)算法设计:使用回溯算法子集树来解决,对于给定的集合 data = {x 1 , x 2 , ......, x n } 和正整数 targetValue,计算 data 的一个子集 data1,满足【x 1 + x 2 + ...... + x n = targetValue (x € data1)】 (3)算法代码: public class SubsetSum { /** * 目标值 */ private static Integer targetValue; /** * 当前所选元素之和 */ private static Integer sum = 0; /** * 数据个数 */ private static Integer num; /** * 未确定值 */ private static Integer indeterminacyValue = 0; /** * 数据数组 */ private static