树形问题
leetcode:17
1 字符串的合法性 (是否包括1,*和#号键)
2 空字符串
3 多个解的顺序
部分源代码如下:
在这里插入代码片
#include<cstring>
using namespace std;
private:
const string letterMap[10]={
" ",//0
"",//1
"abc",//2
"def",
"ghi",
"jkl",
"mno",
"pqrs",
"tuv",
"wxyz"
}
void findCombination(const string &digits, int index, const string &s){
if(index==digits.size()){
//保存s
return;
}
char c = digits[index];
assert(c>='0' && c<='9' && c!='1');
string letters=letterMap[c-'0'];//找到当前数字对应的阿斯玛值
for(int i=0; i<letters.size();i++)
findCombinations(digits,index+1,s+letters[i]);
return;
}
class Solution{
public:
vector<string> letterCombinations(string digits){
}
};
int main(){
return 0;
}
8-23
递归调用的一个重要特征就是要返回–回溯,回溯法是暴力解法的一个主要实现手段
leetcode 93:
返回所有合法的ip地址
leetcode 131
返回所有拆分的可能,所有拆分的子串都是回文串
回溯算法的应用:排列问题
leetcode 46
返回所有元素排列的可能
递归形式如下:
部分源代码如下:
在这里插入代码片
vector<vector<string>solveNQueens(int n){
}
private:
vector<vector<int>> res;
vector<bool> used;//来判断数组中第i个元素是否在p中
void generatePermutation(const vector<int &nums, int index, vector<int>& p){
if(index==nums.size()){
res.push_back(p);
return;
}
for(int i=0;i<nums.size();i++)
if(!used[i]){
//将nums[i]添加在p中
p.push_back(nums[i]);
used[i]=true;
generatePermutation(nums,index+1,p);
p.pop_back();
used[i]=false; //状态进行回溯
}
}
public:
vector<vector<int>> permute(vector<int>& nums){
res.clear();
if(nums.size()==0)
return res;
used=vector<bool>(nums.size(),false);
vector<int> p;
generatePermutation(nums,0,p);
return res;
}
思考题:leetcode 47
8-45 组合问题
leetcode 77
部分代码如下:
在这里插入代码片
private:
vector<vector<int>> res;
void generateCombinations(int n, int k, int start, vector<int> &c){
if(c.size()==k){
res.push_back(c);
return;
}
for(int i=start;i<=n;i++){
c.push_back(i);
genenrateCombinations(n,k,i+1,c)
c.pop_back();
}
return;
vector<vector<int>> combine(int n, int k){
res.clear();
if(n<=0||k<=0||k>n)
return res;
vector<int>c;
generateCombinations(n,k,1,c);
return res;
}
优化思想:剪枝
leetcode 39
leetcode 40
leetcode 216
leetcode 78
leetcode 90
leetcode 401
8-67 二维平面上使用回溯法
leetcode79
方向:为顺时针方向,上右下左
部分代码如下:
在这里插入代码片
private:
int d[4][2]={{-1,0},{0,1},{1,0},{0,-1}} ;
int m,n;
vector<vector<bool>> visited;
bool inArea(int x, int y){
return x>=0 && x<m && y>=0 && y<n;
}
//从board[startx][starty]开始,寻找word【index...word.size()]
bool searchWord(const vector<vector<char>> &board, const string& word, int index,
int startx,int starty){
if(index==word.size()-1)
return board[startx][starty]==qord[index];
if(board[startx][starty]==word[index]){
visited[startx][starty]=true;
//从startx,starty出发,向四个方向寻找
for(int i=0; i<4; i++){
int newx=startx+d[i][0];
int newy=starty+d[i][1];
if(inArea(newx,newy) && !visited[newx][newy] && searchWord(board,word,index+1,newx,newy)
return true;
}
visited[startx][starty]=false;
}
}
bool exsit(vector<vector<char>>& board, string word){
m=board.size();
asser(m>0);
n=board[0].size();
visited=vector<vector<bool>>(m,vector<bool>(n,false));
for(int i=0;i<board.size(); i++){
for(int j=0; j<board[i].size(); j++)
if(searchWord(board,word,0,i,j))
return true;
return false;
}
}
floodfill算法,一类经典问题
leetcode 200 number of islands
从初始点开始,来一个深度优先遍历
部分代码如下:
在这里插入代码片
using namespace std;
class Solution{
private:
int d[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
int m,n; //m,n分别存储陆地的长宽度
vector<vector<bool>> visited;//标记已经被访问过的陆地
bool inArea(int x, int y){
return x>=0 && x<m && y>=0 && y<n;
}
void dfs(vector<vector<char>>& grid,int x,int y){
visited[x][y]=true;
for(int i=0; i<4; i++){
int newx=x+d[i][0];
int newy=y+d[i][1];
if(inArea(newx,newy) && !visited[newx][newy] && grid[newx][newy]=='1')
dfs(drid,newx,newy);
}
return;
}
public:
int numIsLands(vector<vector<char>>& grid){
m=grid.size();
if(m==0){
return 0;
}
n=grid[0].size();
visited=vector<vector<bool>>(m,vector<bool>(n,false));
int res=0;
for(int i=0; i<m;i++)
for(int j=0;j<n;j++)
if(grid[i][j]=='1' && !visited[i][j]){
res++;
dfs(grid,i,j);
}
}
};
int main(){
return 0;
}
leetcode 130 包围字符
leetcode;417
回溯法是经典人工智能的基础
八皇后问题的解:
先来看看四皇后问题:
快速判断不合法的情况
可以发现每个对角线各个空格元素相加为定值
第二个对角线:可以发现相减是一个定值
n皇后的优化问题:
leetcode 52;
求n皇后问题的所有解的个数
leetcode:37
求解数独问题