dfs+回溯专题
Leetcode.17电话号码的字母组合
Leetcode.79单词搜索 (递归跳出条件的顺序很nb if(word[u]!=board[x][y])return false;
if(u==word.size()-1)return true;)
Leetcode.46全排列
Leetcode.47全排列 II (不会,难点:判重,想死我了,visit 代表位置是否被visit过了)
Leetcode.78子集 (上一题变题,难点:判重,visit 代表数是否被visit过了)
Leetcode.子集 II (再让我做一遍可能还不大行)
Leetcode.216组合总和 III
Leetcode.52N皇后 II (被自己厉害到了,和大佬思路一样dfs(row))
Leetcode.37解数独 (递归先正确化,再判断跳出)
Leetcode.473火柴拼正方形 (剪枝例题)
*不重复->递归函数需要start参数
一、Leetcode.17电话号码的字母组合
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
string anniu[8]={"abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
vector<string> letterCombinations(string digits) {
if(digits.empty())return vector<string>();
vector<string>ans(1,"");
for(auto digit:digits){
vector<string>now;
for(int i=0;i<anniu[digit-'2'].size();i++){
for(int j=0;j<ans.size();j++)
now.push_back(ans[j]+anniu[digit-'2'][i]);
}
ans=now;
}
return ans;
}
二、Leetcode.79单词搜索
给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
int m,n;
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
bool dfs(vector<vector<char>>& board,int x,int y,string& word,int u){
if(board[x][y]!=word[u])return false;
if(u==word.size()-1)return true;
board[x][y]='.';
for(int i=0;i<4;i++){
int a=x+dx[i];
int b=y+dy[i];
if(a>=0&&a<m&&b>=0&&b<n){
if(dfs(board,a,b,word,u+1))return true;
}
}
board[x][y]=word[u];
return false;
}
bool exist(vector<vector<char>>& board, string word) {
if(board.size()==0||board[0].size()==0)return false;
m=board.size();
n=board[0].size();
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(dfs(board,i,j,word,0)==true)
return true;
}
}
return false;
}
三、Leetcode.46全排列
给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
int n;
vector<bool>visit;
vector<vector<int>>ans;
vector<int>path;
vector<vector<int>> permute(vector<int>& nums) {
n=nums.size();
visit=vector<bool>(n);
dfs(nums,0);
return ans;
}
void dfs(vector<int>& nums,int u){
if(u==n){
ans.push_back(path);
return ;
}
for(int i=0;i<n;i++){
if(visit[i]==0){
visit[i]=1;
path.push_back(nums[i]);
dfs(nums,u+1);
path.pop_back();
visit[i]=0;
}
}
}
四、Leetcode.47全排列 II
给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
int n;
vector<vector<int>>ans;
vector<int>path;
vector<bool>visit;
void dfs(vector<int>& nums,int u,int start){//第u个数
if(u==n){
ans.push_back(path);
return;
}
for(int i=start;i<n;i++){
if(visit[i]==false){
visit[i]=true;
path[i]=nums[u];
dfs(nums,u+1,u+1<n&&nums[u+1]==nums[u]?i+1:0);
visit[i]=false;
}
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
sort(nums.begin(),nums.end());
n=nums.size();
path=vector<int>(n);
visit=vector<bool>(n);
dfs(nums,0,0);
return ans;
}
五、Leetcode.78子集
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>>ans;
for(int i=0;i<(1<<nums.size());i++)
{
vector<int>temp;
for(int j=0;j<nums.size();j++)
{
if(i>>j&1)temp.push_back(nums[j]);
}
ans.push_back(temp);
}
return ans;
}
六、Leetcode.90子集 II
给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
vector<vector<int>>ans;
vector<int>path;
void dfs(vector<int>& nums,int u){
if(u==nums.size()){
ans.push_back(path);
return;
}
int k=0;
while(u+k<nums.size()&&nums[u+k]==nums[u]){
k++;
}
for(int i=0;i<=k;i++){
dfs(nums,u+k);
path.push_back(nums[u]);
}
for(int i=0;i<=k;i++)path.pop_back();
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(),nums.end());
dfs(nums,0);
return ans;
}
七、Leetcode.216组合总和 III
找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:
只使用数字1到9
每个数字 最多使用一次
返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。
vector<vector<int>>ans;
vector<int>path;
void dfs(int k,int start,int n){
if(k==0){
if(n==0)ans.push_back(path);
return;
}
for(int i=start;i<=9;i++){
path.push_back(i);
dfs(k-1,i+1,n-i);
path.pop_back();
}
}
vector<vector<int>> combinationSum3(int k, int n) {
dfs(k,1,n);
return ans;
}
八、Leetcode.52N皇后 II
n 皇后问题 研究的是如何将 n 个皇后放置在 n × n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回 n 皇后问题 不同的解决方案的数量。
int ans=0;
int n;
vector<bool>col,d,ud;
void dfs(int level){
if(level==n){
ans++;
return;
}
for(int i=0;i<n;i++){
if(!col[i]&&!d[i+level]&&!ud[i-level+n]){
col[i]=d[i+level]=ud[i-level+n]=true;
dfs(level+1);
col[i]=d[i+level]=ud[i-level+n]=false;
}
}
}
int totalNQueens(int _n) {
n=_n;
col=vector<bool>(n);
d=ud=vector<bool>(2*n);
dfs(0);
return ans;
}
九、Leetcode.37解数独
编写一个程序,通过填充空格来解决数独问题。
数独的解法需 遵循如下规则:
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
数独部分空格内已填入了数字,空白格用 ‘.’ 表示。
bool row[9][10]={0};
bool col[9][10]={0};
bool cell[3][3][10]={0};
bool dfs(vector<vector<char>>& board,int x,int y){
if(y==9)x++,y=0;
if(x==9)return true;
if(board[x][y]!='.')return dfs(board,x,y+1);
for(int i=0;i<9;i++){
if(!row[x][i]&&!col[y][i]&&!cell[x/3][y/3][i]){
row[x][i]=col[y][i]=cell[x/3][y/3][i]=true;
board[x][y]='1'+i;
if(dfs(board,x,y+1))return true;
board[x][y]='.';
row[x][i]=col[y][i]=cell[x/3][y/3][i]=false;
}
}
return false;
}
void solveSudoku(vector<vector<char>>& board) {
for(int i=0;i<9;i++)
for(int j=0;j<9;j++){
if(board[i][j]!='.'){
row[i][board[i][j]-'1']=true;
col[j][board[i][j]-'1']=true;
cell[i/3][j/3][board[i][j]-'1']=true;
}
}
dfs(board,0,0);
}
十、Leetcode.473火柴拼正方形
你将得到一个整数数组 matchsticks ,其中 matchsticks[i] 是第 i 个火柴棒的长度。你要用 所有的火柴棍 拼成一个正方形。你 不能折断 任何一根火柴棒,但你可以把它们连在一起,而且每根火柴棒必须 使用一次 。
如果你能使这个正方形,则返回 true ,否则返回 false 。
vector<bool>visit;
bool dfs(vector<int>& matchsticks,int u,int cur,int length){
if(cur==length){
u++,cur=0;
}
if(u==4)return true;
for(int i=0;i<matchsticks.size();i++){
if(!visit[i]&&matchsticks[i]+cur<=length){
visit[i]=true;
if(dfs(matchsticks,u,cur+matchsticks[i],length))return true;
visit[i]=false;
if(cur==0)return false;
if(cur+matchsticks[i]==length)return false;
while(i+1<matchsticks.size()&&matchsticks[i]==matchsticks[i+1])i++;
}
}
return false;
}
bool makesquare(vector<int>& matchsticks) {
int sum=0;
for(int i=0;i<matchsticks.size();i++){
sum+=matchsticks[i];
}
if(matchsticks.size()==0||sum%4)return false;
visit=vector<bool>(matchsticks.size());
sort(matchsticks.begin(),matchsticks.end());
reverse(matchsticks.begin(),matchsticks.end());
return dfs(matchsticks,0,0,sum/4);
}