【10】Regular Expression Matching

【17】Letter Combinations of a Phone Number

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

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

n = 3

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

题解:dfs生成。

 class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string> res;
string str;
int left = n, right = n;
dfs(str, res, left, right);
return res;
}
void dfs(string& str, vector<string>& res, int left, int right) {
if (left == && right == ) {
res.push_back(str);
return;
}
if (left <= right && left - >= ) {
str += "(";
dfs(str, res, left-, right);
str.pop_back();
}
if (left < right && right - >= ) {
str += ")";
dfs(str, res, left, right - );
str.pop_back();
}
}
};

【37】Sudoku Solver (2019年3月18日,google tag)

题意:填数独

题解:backtracking,唯一的难点是判断每一个 3 * 3 的 block 是否合法的时候,坐标的判断需要点技巧。

 class Solution {
public:
void solveSudoku(vector<vector<char>>& board) {
dfs(board);
return;
}
const int n = , size = ;
bool dfs(vector<vector<char>>& board) {
for (int i = ; i < n; ++i) {
for (int j = ; j < n; ++j) {
if (board[i][j] == '.') {
for (char c = ''; c <= ''; ++c) {
if (isValid(board, i, j, c)) {
board[i][j] = c;
if (dfs(board)) {return true;}
board[i][j] = '.';
}
}
return false;
}
}
}
return true;
}
bool isValid(vector<vector<char>>& board, int r, int c, char x) {
const int idxR = (r / size) * , idxC = (c / size) * ;
for (int i = ; i < n; ++i) {
if (board[r][i] == x || board[i][c] == x) {return false;}
if (board[idxR+i/][idxC+i%] == x) {return false;}
}
return true;
}
};

【39】Combination Sum

【40】Combination Sum II

【44】Wildcard Matching

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

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

题解:dfs

 class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {
dfs(nums);
return ret;
}
vector<int> arr;
vector<vector<int>> ret;
void dfs(const vector<int>& nums) {
if (arr.size() == nums.size()) {
ret.push_back(arr);
return;
}
for (int i = ; i < nums.size(); ++i) {
set<int> st(arr.begin(), arr.end());
if (st.find(nums[i]) != st.end()) { continue; }
arr.push_back(nums[i]);
dfs(nums);
arr.pop_back();
}
return;
}
};

【47】Permutations II (2019年2月17日,有重复元素的全排列。今天周赛的第四题 996. Number of Squareful Arrays)

写一个有重复元素的全排列。

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

题解:我们可以先 sort 一下数组,然后用一个临时的array,存放现在结果,重点是遇到重复元素的时候如何避免生成重复的序列。如果当前想放进列表的元素已经访问过了,就continue,如果当前想放进列表的元素和它前一个元素的值一样,但是前一个元素还没有放进数组里面,那么这个元素肯定不能放在数组里面,比如说原数组是[2, 2],对应下标是[0, 1],如果第一个2还没有在列表里面,那么第二个2就肯定不让它在列表里面。因为如果第二个2在列表里面并且在第一个2前面,就有 [1,0] 和 [0,1] 的两种排列。

 class Solution {
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
const int n = nums.size();
sort(nums.begin(), nums.end());
vector<vector<int>> ret;
vector<int> visited(n, ), arr;
dfs(nums, ret, arr, visited);
return ret;
}
void dfs(vector<int>& nums, vector<vector<int>>& ret, vector<int>& arr, vector<int>& visited) {
if (arr.size() == nums.size()) {
ret.push_back(arr);
return;
}
for (int i = ; i < nums.size(); ++i) {
if (visited[i]) {continue;}
if (i - >= && nums[i] == nums[i-] && !visited[i-]) {continue;}
arr.push_back(nums[i]);
visited[i] = ;
dfs(nums, ret, arr, visited);
arr.pop_back();
visited[i] = ;
}
}
};

【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],

题解:直接回溯。

 class Solution {
public:
vector<vector<int>> ret;
vector<vector<int>> combine(int n, int k) {
vector<int> nums;
dfs(nums, , n, k);
return ret;
}
void dfs(vector<int>& nums, int cur, const int n, const int k) {
if (nums.size() == k) {
ret.push_back(nums);
return;
}
for (int i = cur; i <= n; ++i) {
nums.push_back(i);
dfs(nums, i + , n, k); //这里注意不要写错了。 我有时候会写成 dfs(nums, cur + 1, n, k);
nums.pop_back();
}
return;
}
};

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

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

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

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

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

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

 class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
n = board.size(), m = board[].size();
for (int i = ; i < n; ++i) {
for (int j = ; j < m; ++j) {
if (board[i][j] == word[]) {
vector<vector<int>> visit(n, vector<int>(m, ));
visit[i][j] = ;
if (dfs(board, i, j, word, , visit)) {
return true;
}
}
}
}
return false;
}
int n, m;
bool dfs(vector<vector<char>>& board, int x, int y, const string word, int cur, vector<vector<int>>& visit) {
if (cur + == word.size()) {
return true;
}
for (int i = ; i < ; ++i) {
int newx = x + dirx[i], newy = y + diry[i];
if (newx >= && newx < n && newy >= && newy < m && !visit[newx][newy] && board[newx][newy] == word[cur+]) {
visit[newx][newy] = ;
if (dfs(board, newx, newy, word, cur + , visit)) {
return true;
}
visit[newx][newy] = ;
}
}
return false;
}
int dirx[] = {-, , , };
int diry[] = {, -, , };
};

【89】Gray Code

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

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

Input: [,,]
Output:
[
[],
[],
[,,],
[,],
[,],
[]
]

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

 class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
const int n = nums.size();
vector<vector<int>> ret;
set<vector<int>> stRet;
vector<int> temp;
dfs(nums, stRet, , temp);
for (auto ele : stRet) {
ret.push_back(ele);
}
return ret;
}
void dfs(const vector<int>& nums, set<vector<int>>& st, int cur, vector<int>& temp) {
vector<int> t1 = temp;
sort(t1.begin(), t1.end());
st.insert(t1);
if (cur == nums.size()) {return;}
for (int i = cur; i < nums.size(); ++i) {
temp.push_back(nums[i]);
dfs(nums, st, i+, temp);
temp.pop_back();
}
}
};

2019年2月25日更新一个更好的解法:

如果当前层次有两个一样的数,一定不会选择后面的那个数字。(可以参考 有重复元素的permutation)

 class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
vector<vector<int>> res;
sort(nums.begin(), nums.end());
if (nums.empty()) {return res;}
vector<int> path;
dfs(nums, res, path, );
return res;
}
void dfs(vector<int>& nums, vector<vector<int>>& res, vector<int>& path, int start) {
res.push_back(path);
for (int i = start; i < nums.size(); ++i) {
if (i != start && nums[i] == nums[i-]) {continue;}
path.push_back(nums[i]);
dfs(nums, res, path, i + );
path.pop_back();
}
}
};

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

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

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

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

 class Solution {
public:
vector<string> restoreIpAddresses(string s) {
const int n = s.size();
vector<string> ret;
if (n == ) {return ret;}
string temp;
dfs(s, , ret, temp, );
return ret;
}
void dfs(const string s, int cur, vector<string>& ret, string& temp, int part) {
if (cur == s.size() && part == ) {
ret.push_back(temp);
return;
}
if (part >= ) {return;}
string num;
if (s[cur] == '') {
string oriTemp = temp;
num = string(, s[cur]);
temp += temp.empty() ? (num) : ("." + num);
dfs(s, cur + , ret, temp, part + );
temp = oriTemp;
} else {
string oriTemp = temp;
for (int k = ; k <= ; ++k) {
if (cur + k >= s.size()) {break;}
num += s[cur + k];
int inum = stoi(num);
if (inum < || inum > ) {break;}
temp += temp.empty() ? (num) : ("." + num);
dfs(s, cur + k + , ret, temp, part + );
temp = oriTemp;
}
}
}
};

【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 了。

 // WA到吐了,太多情况
class Solution {
public:
vector<int> splitIntoFibonacci(string S) {
vector<int> ans;
if (S.empty()) { return ans; } //S如果是“000”是可以的,所以需要留着dfs.
return dfs(S, ans, ) ? ans : vector<int>{};
}
bool dfs(string S, vector<int>& ans, int cur_idx) {
int n = S.size();
if (cur_idx == n) {
return ans.size() >= ? true : false;
}
for (int i = cur_idx; i < n; ++i) {
if (ans.size() < ) {
string strNumber = S.substr(cur_idx, i - cur_idx + );
if (strNumber.size() > || strNumber.size() > && strNumber[] == '') {continue; }
long long number = stoll(strNumber);
if (number > INT_MAX) {continue;}
ans.push_back(number);
if (dfs(S, ans, i + )) {
return true;
}
ans.pop_back();
} else {
int ansSize = ans.size();
int num1 = ans.back(), num2 = ans[ansSize - ];
string strNumber = S.substr(cur_idx, i - cur_idx + );
if (strNumber.size() > || strNumber.size() > && strNumber[] == '') {continue; }
long long num3 = stoll(strNumber);
if (num3 > INT_MAX) {continue;}
if (num1 + num2 == num3) {
ans.push_back(num3);
if (dfs(S, ans, i + )){
return true;
}
ans.pop_back();
}
}
}
return false;
}
};

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

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

  1. N-Queens And N-Queens II [LeetCode] + Generate Parentheses[LeetCode] + 回溯法

    回溯法 百度百科:回溯法(探索与回溯法)是一种选优搜索法,按选优条件向前搜索,以达到目标.但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步又一次选择,这样的走不通就退回再走的技术为回溯法 ...

  2. Leetcode 回溯法 典型例题

    那些要求列举所有的情况,或者说所有的情况都要探讨一下的例题,一般都可以考虑回溯法. 当遇到一个可以用到回溯法的时候需要按照如下步骤进行: 1.确定问题一个可以用到回溯法的时候需要按照如下步骤进行: 1 ...

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

    [600] Non-negative Integers without Consecutive Ones [629] K Inverse Pairs Array [638] Shopping Offe ...

  4. 【LeetCode】Recursion(共11题)

    链接:https://leetcode.com/tag/recursion/ 247 Strobogrammatic Number II (2019年2月22日,谷歌tag) 给了一个 n,给出长度为 ...

  5. 【LeetCode】数学(共106题)

    [2]Add Two Numbers (2018年12月23日,review) 链表的高精度加法. 题解:链表专题:https://www.cnblogs.com/zhangwanying/p/979 ...

  6. 【LeetCode】BFS(共43题)

    [101]Symmetric Tree 判断一棵树是不是对称. 题解:直接递归判断了,感觉和bfs没有什么强联系,当然如果你一定要用queue改写的话,勉强也能算bfs. // 这个题目的重点是 比较 ...

  7. 【LeetCode】树(共94题)

    [94]Binary Tree Inorder Traversal [95]Unique Binary Search Trees II (2018年11月14日,算法群) 给了一个 n,返回结点是 1 ...

  8. LeetCode 回溯法 别人的小结 八皇后 递归

    #include <iostream> #include <algorithm> #include <iterator> #include <vector&g ...

  9. [Leetcode] Backtracking回溯法解题思路

    碎碎念: 最近终于开始刷middle的题了,对于我这个小渣渣确实有点难度,经常一两个小时写出一道题来.在开始写的几道题中,发现大神在discuss中用到回溯法(Backtracking)的概率明显增大 ...

随机推荐

  1. YottaChain主网全面上线预示商业应用的落地区块链云存储不一样的云

    Yottachain存储网12月24日平安夜全面启动,意味着全球首个可商用的区块链存储公链全面落地.对于数据存储来说,小到我们个人的照片文档,大到政企机构数据库资料,都是互联网生活中如影随形的标配. ...

  2. Dubbo学习-5-监控中心simpleMonitor搭建

    之前已经下载好的dubbo-admin-master源码中,有dubbo-monitor-simple工程,同理,使用maven命令打包成一个可执行的jar包: 1.进入dubbo-monitor-s ...

  3. linux运维、架构之路-ansible批量管理

    一.ansible软件 1.介绍 ①ansible是一个基于Python开发的自动化运维工具 ②其功能实现基于SSH远程连接服务 ③ansible可以实现批量系统配置.批量软件部署.批量文件拷贝.批量 ...

  4. [CF1081H]Palindromic Magic

    题意:给两个字符串\(a,b\),求出有多少种不同的字符串能通过从第一个串中取出一个回文串,从第二个串中取出一个回文串,按顺序拼接得到. 题解:证明?看官方题解吧 一些定义: 回文串拆分:\(s=ab ...

  5. BaseFragment 基类

    package com.test.mvp.mvpdemo.mvp.v6.basemvp; import android.os.Bundle;import android.support.annotat ...

  6. Linux 用户和组信息

    linux系统是一个多用户多任务的分时操作系统,任何一个要使用系统资源的用户,都必须首先向系统管理员申请一个账号.在使用linux操作系统时候,通常我们会遇到对多用户进行管理.比如: 用户账号的添加. ...

  7. STM32 ADC基础与多通道采样

    12位ADC是一种逐次逼近型模拟数字数字转换器.它有多达18个通道,可测量16个外部和2个内部信号源.ADC的输入时钟不得超过14MHZ,它是由PCLK2经分频产生.如果被ADC转换的模拟电压低于低阀 ...

  8. leetcode 217. 存在重复元素 (python)

    给定一个整数数组,判断是否存在重复元素. 如果任何值在数组中出现至少两次,函数返回 true.如果数组中每个元素都不相同,则返回 false. 示例 1: 输入: [1,2,3,1]输出: true示 ...

  9. Vagrant 手册之同步目录 - VirtualBox

    原文地址 如果你使用的 provider 是 VirtualBox,那么 VirtualBox 同步目录就是默认的同步目录类型.这些同步目录使用 VirtualBox 的共享目录系统来同步客户机跟宿主 ...

  10. [Bzoj1731]排队布局

    洛谷上的翻译是真的哲学♂♂♂ 非常van的题目传送门♂♂♂ 个人认为这题充其量也就是个蓝(nan)题,首先处理-1的情况,-1的情况是不等式组无解,按照差分约束的规则,无解说明出现了负环,先跑一遍以0 ...