【LeetCode】回溯法 backtracking(共39题)

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }

【10】Regular Expression Matching

【17】Letter Combinations of a Phone Number

【22】Generate Parentheses (2019年2月13日)

给了一个N,生成N对括号的所有情况的字符串。

n = 3

[
  "((()))",
  "(()())",
  "(())()",
  "()(())",
  "()()()"
]

题解:dfs生成。

 1 class Solution {
 2 public:
 3     vector<string> generateParenthesis(int n) {
 4         vector<string> res;
 5         string str;
 6         int left = n, right = n;
 7         dfs(str, res, left, right);
 8         return res;
 9     }
10     void dfs(string& str, vector<string>& res, int left, int right) {
11         if (left == 0 && right == 0) {
12             res.push_back(str);
13             return;
14         }
15         if (left <= right && left - 1 >= 0) {
16             str += "(";
17             dfs(str, res, left-1, right);
18             str.pop_back();
19         }
20         if (left < right && right - 1 >= 0) {
21             str += ")";
22             dfs(str, res, left, right - 1);
23             str.pop_back();
24         }
25     }
26 };

【37】Sudoku Solver

【39】Combination Sum

【40】Combination Sum II

【44】Wildcard Matching

【46】Permutations (2019年1月23日,谷歌tag复习)(M)

给了一个distinct numbers 的数组,返回所有的排列。

题解:dfs

 1 class Solution {
 2 public:
 3     vector<vector<int>> permute(vector<int>& nums) {
 4         dfs(nums);
 5         return ret;
 6     }
 7     vector<int> arr;
 8     vector<vector<int>> ret;
 9     void dfs(const vector<int>& nums) {
10         if (arr.size() == nums.size()) {
11             ret.push_back(arr);
12             return;
13         }
14         for (int i = 0; i < nums.size(); ++i) {
15             set<int> st(arr.begin(), arr.end());
16             if (st.find(nums[i]) != st.end()) { continue; }
17             arr.push_back(nums[i]);
18             dfs(nums);
19             arr.pop_back();
20         }
21         return;
22     }
23 };

【47】Permutations II

【51】N-Queens

【52】N-Queens II

【60】Permutation Sequence

【77】Combinations (2019年1月21日,算法群打卡题)

Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.

Input: n = 4, k = 2
Output:
[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
] 

题解:直接回溯。

 1 class Solution {
 2 public:
 3     vector<vector<int>> ret;
 4     vector<vector<int>> combine(int n, int k) {
 5         vector<int> nums;
 6         dfs(nums, 1, n, k);
 7         return ret;
 8     }
 9     void dfs(vector<int>& nums, int cur, const int n, const int k) {
10         if (nums.size() == k) {
11             ret.push_back(nums);
12             return;
13         }
14         for (int i = cur; i <= n; ++i) {
15             nums.push_back(i);
16             dfs(nums, i + 1, n, k);  //这里注意不要写错了。 我有时候会写成 dfs(nums, cur + 1, n, k);
17             nums.pop_back();
18         }
19         return;
20     }
21 };

【78】Subsets (相似的题目见 90 题)

给了一个 distinct 的数组,返回它所有的子集。

题解见位运算专题【78】题,一样的。https://www.cnblogs.com/zhangwanying/p/9886589.html

【79】Word Search (2019年1月25日,谷歌tag复习) (Medium)

给了一个单词板和一个单词,四联通,问能不能在板子上面找到这个单词。

题解:backtracking,注意边界哇哭死,没有一次AC

 1 class Solution {
 2 public:
 3     bool exist(vector<vector<char>>& board, string word) {
 4         n = board.size(), m = board[0].size();
 5         for (int i = 0; i < n; ++i) {
 6             for (int j = 0; j < m; ++j) {
 7                 if (board[i][j] == word[0]) {
 8                     vector<vector<int>> visit(n, vector<int>(m, 0));
 9                     visit[i][j] = 1;
10                     if (dfs(board, i, j, word, 0, visit)) {
11                         return true;
12                     }
13                 }
14             }
15         }
16         return false;
17     }
18     int n, m;
19     bool dfs(vector<vector<char>>& board, int x, int y, const string word, int cur, vector<vector<int>>& visit) {
20         if (cur + 1 == word.size()) {
21             return true;
22         }
23         for (int i = 0; i < 4; ++i) {
24             int newx = x + dirx[i], newy = y + diry[i];
25             if (newx >= 0 && newx < n && newy >= 0 && newy < m && !visit[newx][newy] && board[newx][newy] == word[cur+1]) {
26                 visit[newx][newy] = 1;
27                 if (dfs(board, newx, newy, word, cur + 1, visit)) {
28                     return true;
29                 }
30                 visit[newx][newy] = 0;
31             }
32         }
33         return false;
34     }
35     int dirx[4] = {-1, 0, 1, 0};
36     int diry[4] = {0, -1, 0, 1};
37 };

【89】Gray Code

【90】Subsets II (算法群,2018年11月21日)

给了一个有重复数字的数组,返回它所有的unique子集。

Input: [1,2,2]
Output:
[
  [2],
  [1],
  [1,2,2],
  [2,2],
  [1,2],
  []
]

题解:回溯法。用set去重,有一点需要注意的是,千万不能每次递归的时候对 现在vector的状态sort一下,不然递归回溯的时候肯定有问题的。

 1 class Solution {
 2 public:
 3     vector<vector<int>> subsetsWithDup(vector<int>& nums) {
 4         const int n = nums.size();
 5         vector<vector<int>> ret;
 6         set<vector<int>> stRet;
 7         vector<int> temp;
 8         dfs(nums, stRet, 0, temp);
 9         for (auto ele : stRet) {
10             ret.push_back(ele);
11         }
12         return ret;
13     }
14     void dfs(const vector<int>& nums, set<vector<int>>& st, int cur, vector<int>& temp) {
15         vector<int> t1 = temp;
16         sort(t1.begin(), t1.end());
17         st.insert(t1);
18         if (cur == nums.size()) {return;}
19         for (int i = cur; i < nums.size(); ++i) {
20             temp.push_back(nums[i]);
21             dfs(nums, st, i+1, temp);
22             temp.pop_back();
23         }
24     }
25 };

【93】Restore IP Addresses (2019年2月14日)

给了一个串纯数字的字符串,在字符串里面加‘.’,返回所有合法的ip字符串。

Input: "25525511135"
Output: ["255.255.11.135", "255.255.111.35"] 

题解:backtracking,用一个新的字符串保存当前的ip字符串。ipv4的每一个小段必须是[0, 255],四个小段。

 1 class Solution {
 2 public:
 3     vector<string> restoreIpAddresses(string s) {
 4         const int n = s.size();
 5         vector<string> ret;
 6         if (n == 0) {return ret;}
 7         string temp;
 8         dfs(s, 0, ret, temp, 0);
 9         return ret;
10     }
11     void dfs(const string s, int cur, vector<string>& ret, string& temp, int part) {
12         if (cur == s.size() && part == 4) {
13             ret.push_back(temp);
14             return;
15         }
16         if (part >= 4) {return;}
17         string num;
18         if (s[cur] == ‘0‘) {
19             string oriTemp = temp;
20             num = string(1, s[cur]);
21             temp += temp.empty() ? (num) : ("." + num);
22             dfs(s, cur + 1, ret, temp, part + 1);
23             temp = oriTemp;
24         } else {
25             string oriTemp = temp;
26             for (int k = 0; k <= 2; ++k) {
27                 if (cur + k >= s.size()) {break;}
28                 num += s[cur + k];
29                 int inum = stoi(num);
30                 if (inum < 1 || inum > 255) {break;}
31                 temp += temp.empty() ? (num) : ("." + num);
32                 dfs(s, cur + k + 1, ret, temp, part + 1);
33                 temp = oriTemp;
34             }
35         }
36     }
37 };

【126】Word Ladder II

【131】Palindrome Partitioning

【140】Word Break II(2018年12月19日,算法群,类似题目 472. DFS专题)

【211】Add and Search Word - Data structure design

【212】Word Search II

【216】Combination Sum III

【254】Factor Combinations

【267】Palindrome Permutation II

【291】Word Pattern II

【294】Flip Game II

【306】Additive Number

【320】Generalized Abbreviation

【351】Android Unlock Patterns

【357】Count Numbers with Unique Digits

【401】Binary Watch

【411】Minimum Unique Word Abbreviation

【425】Word Squares

【526】Beautiful Arrangement

【691】Stickers to Spell Word

【784】Letter Case Permutation

【842】Split Array into Fibonacci Sequence

给了一个字符串 S,看能不能通过分割字符串,把字符串搞成一个斐波那契数组。(1 <= S.size() <= 200)

题解:就是暴力搜,但是WA吐了快,有几个点要注意,如果是 “000” 这种是可以返回的,返回 [0, 0, 0]。然后如果分割的字符串太长的就要continue,不然你 long long 也没有用,200位肯定超过 long long 了。

 1 // WA到吐了,太多情况
 2 class Solution {
 3 public:
 4     vector<int> splitIntoFibonacci(string S) {
 5         vector<int> ans;
 6         if (S.empty()) { return ans; } //S如果是“000”是可以的,所以需要留着dfs.
 7         return dfs(S, ans, 0) ? ans : vector<int>{};
 8     }
 9     bool dfs(string S, vector<int>& ans, int cur_idx) {
10         int n = S.size();
11         if (cur_idx == n) {
12             return ans.size() >= 3 ? true : false;
13         }
14         for (int i = cur_idx; i < n; ++i) {
15             if (ans.size() < 2) {
16                 string strNumber = S.substr(cur_idx, i - cur_idx + 1);
17                 if (strNumber.size() > 10 || strNumber.size() > 1 && strNumber[0] == ‘0‘) {continue; }
18                 long long number = stoll(strNumber);
19                 if (number > INT_MAX) {continue;}
20                 ans.push_back(number);
21                 if (dfs(S, ans, i + 1)) {
22                     return true;
23                 }
24                 ans.pop_back();
25             } else {
26                 int ansSize = ans.size();
27                 int num1 = ans.back(), num2 = ans[ansSize - 2];
28                 string strNumber = S.substr(cur_idx, i - cur_idx + 1);
29                 if (strNumber.size() > 10 || strNumber.size() > 1 && strNumber[0] == ‘0‘) {continue; }
30                 long long num3 = stoll(strNumber);
31                 if (num3 > INT_MAX) {continue;}
32                 if (num1 + num2 == num3) {
33                     ans.push_back(num3);
34                     if (dfs(S, ans, i + 1)){
35                         return true;
36                     }
37                     ans.pop_back();
38                 }
39             }
40         }
41         return false;
42     }
43 };

但是好像我的方法巨慢,可以看看discuss怎么求解的。

原文地址:https://www.cnblogs.com/zhangwanying/p/9886305.html

时间: 2024-10-03 14:41:46

【LeetCode】回溯法 backtracking(共39题)的相关文章

迷宫问题(MazePath)的求解——利用回溯法(backtracking)

迷宫问题(MazePath)的求解--利用回溯法(backtracking) 1. 迷宫问题的提法 迷宫问题是典型的图的搜索问题. 假设一个迷宫,只有一个入口和一个出口.如果从迷宫的入口到达出口,途中不出现行进方向错误,则得到一条最佳路线. 为此,用一个二维数组maze[m][p]来表示迷宫. (1)当数组元素maze[i][j]=1 (0≤i≤m-1,1≤j≤p-1),表示该位置是墙壁,不能通行. (2)当数组元素maze[i][j]=0 (0≤i≤m-1,1≤j≤p-1),表示该位置是通路,

回溯法(backtracking) 题目整理--------part2

N-Queens 模拟退火不会写 0.0 The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other. Given an integer n, return all distinct solutions to the n-queens puzzle. Each solution contains a distinct bo

【LeetCode】动态规划(下篇共39题)

[600] Non-negative Integers without Consecutive Ones [629] K Inverse Pairs Array [638] Shopping Offers [639] Decode Ways II [646] Maximum Length of Pair Chain [647] Palindromic Substrings [650] 2 Keys Keyboard [651] 4 Keys Keyboard [656] Coin Path [6

【LeetCode】BFS(共43题)

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica } [101]Symmetric Tree 判断一棵树是不是对称. 题解:直接递归判断了,感觉和bfs没有什么强联系,当然如果你一定要用queue改写的话,勉强也能算bfs. // 这个题目的重点是 比较对象是 左子树的左儿子和右子树的右儿子, 左子树的右儿子和右子树的左儿子.不要搞错. // 直接中序遍历的话会有错的情况,最蠢的情况是数字标注改一改.. 1 /** 2

【LeetCode】树(共94题)

[94]Binary Tree Inorder Traversal [95]Unique Binary Search Trees II (2018年11月14日,算法群) 给了一个 n,返回结点是 1 - n 的所有形态的BST. 题解:枚举每个根节点 r, 然后递归的生成左右子树的所有集合,然后做笛卡尔积. 1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *

【LeetCode】数学(共106题)

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica } [2]Add Two Numbers [7]Reverse Integer [8]String to Integer (atoi) [9]Palindrome Number [12]Integer to Roman [13]Roman to Integer [29]Divide Two Integers [43]Multiply Strings [50]Pow(x,

[Leetcode] Backtracking回溯法解题思路

碎碎念: 最近终于开始刷middle的题了,对于我这个小渣渣确实有点难度,经常一两个小时写出一道题来.在开始写的几道题中,发现大神在discuss中用到回溯法(Backtracking)的概率明显增大.感觉如果要顺利的把题刷下去,必须先要把做的几道题题总结一下. 先放上参考的web: https://segmentfault.com/a/1190000006121957 http://summerisgreen.com/blog/2017-07-07-2017-07-07-算法技巧-backtr

回溯法 矩阵中的路径

题目:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径.路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左.右.上.下移动一格.如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子. 这是一个可以用回溯法解决的经典题.首先,在矩阵中任选一个格子作为路径的起点.假设矩阵中某个格子的字符为ch,并且这个格子将对应于路径上的第i个字符.如果路径上的第i个字符不是ch,那么这个格子不可能处在路径上的第i个位置.如果路径上的第i个字符正好是ch,那么到相邻的格子寻找路

Leetcode之回溯法专题-39. 组合总数(Combination Sum)

给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的数字可以无限制重复被选取. 说明: 所有数字(包括 target)都是正整数. 解集不能包含重复的组合. 示例 1: 输入: candidates = [2,3,6,7], target = 7, 所求解集为: [ [7], [2,2,3] ] 示例 2: 输入: candidates = [2,3,5], target