这是思维逻辑中的一棵树
什么是深搜和广搜?
对于问题求解树的不同的遍历方式
什么是搜索剪枝和优化?
排除某些问题的求解树中的子树的遍历过程
设计搜索算法的核心关键点是什么?
设计问题求解树中的状态
广度遍历适合最优化问题
993. 二叉树的堂兄弟节点
使用深搜
class Solution {
public:
int dfs(TreeNode *root, int x, TreeNode *&father){
if(root == nullptr) return -1;
if(root->val == x) return 0;
father = root;
int l;
l = dfs(root->left, x, father);
if(l != -1) return l + 1;
father = root;
l = dfs(root->right, x, father);
if(l != -1) return l + 1;
return -1;
}
bool isCousins(TreeNode* root, int x, int y) {
int d1, d2;
TreeNode *father_x = nullptr, *father_y = nullptr;
d1 = dfs(root, x, father_x);
d2 = dfs(root, y, father_y);
return d1 == d2 && father_x != father_y;
}
};
使用广搜
class Solution {
public:
struct Data{
Data(TreeNode *node = nullptr, TreeNode *father = nullptr, int deepth = 0)
:node(node), father(father), deepth(deepth) {}
TreeNode *node, *father;
int deepth;
};
bool isCousins(TreeNode* root, int x, int y) {
int d1, d2;
TreeNode *father_x = nullptr, *father_y = nullptr;
queue<Data> q;
q.push(Data(root, 0));
while(!q.empty()){
Data cur = q.front();
if(cur.node->val == x) d1 = cur.deepth, father_x = cur.father;
if(cur.node->val == y) d2 = cur.deepth, father_y = cur.father;
if(cur.node->left) {
q.push(Data(cur.node->left, cur.node, cur.deepth + 1));
}
if(cur.node->right) {
q.push(Data(cur.node->right, cur.node, cur.deepth + 1));
}
q.pop();
}
return d1 == d2 && father_x != father_y;
}
};
542. 01 矩阵
class Solution {
public:
struct Data {
Data(int i = 0, int j = 0, int k = 0)
: i(i), j(j), k(k) {}
int i, j, k;
};
void init_queue(
queue<Data> &q, vector<vector<int>> &vis,
int n, int m,
vector<vector<int>> &mat
){
for(int i = 0; i < n; i++){
vis.push_back(vector<int>());
for(int j = 0; j < m; j++){
vis[i].push_back(-1);
}
}
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
if(mat[i][j]) continue;
vis[i][j] = 0;
q.push(Data(i, j, 0));
}
}
return;
}
int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {
int n = mat.size(), m = mat[0].size();
queue<Data> q;
vector<vector<int>> vis;
init_queue(q, vis, n, m, mat);
while(!q.empty()){
Data cur = q.front();
for(int k = 0; k < 4; k++){
int x = cur.i + dir[k][0];
int y = cur.j + dir[k][1];
if(x < 0 || x >= n) continue;
if(y < 0 || y >= m) continue;
if(vis[x][y] != -1) continue;
vis[x][y] = cur.k + 1;
q.push(Data(x, y, cur.k + 1));
}
q.pop();
}
return vis;
};
};
1091. 二进制矩阵中的最短路径
class Solution {
public:
struct Data {
Data(int i = 0, int j = 0, int l = 0)
: i(i), j(j), l(l) {}
int i, j, l;
};
int dir[8][2] = {
0, 1, 1, 0, 0, -1, -1, 0,
1, -1, -1, 1, 1, 1, -1, -1
};
int shortestPathBinaryMatrix(vector<vector<int>>& grid) {
int n = grid.size();
vector<vector<int>> vis;
for(int i = 0; i < n; i++){
vis.push_back(vector<int>(n));
}
queue<Data> q;
if(grid[0][0]) return -1;
vis[0][0] = 1;
q.push(Data(0, 0, 1));
while(!q.empty()){
Data cur = q.front();
if(cur.i == n - 1 && cur.j == n -1) return cur.l;
for(int k = 0; k < 8; k++){
int x = cur.i + dir[k][0];
int y = cur.j + dir[k][1];
if(x < 0 || x >= n) continue;
if(y < 0 || y >= n) continue;
if(grid[x][y]) continue;
if(vis[x][y]) continue;
vis[x][y] = 1;
q.push(Data(x, y, cur.l + 1));
}
q.pop();
}
return -1;
}
};
752. 打开转盘锁
class Solution {
public:
struct Data{
Data(string s = "", int l = 0)
: s(s), l(l){}
string s;
int l;
};
string getS(string &s, int i, int k){
string ret = s;
switch(k) {
case 0: ret[i] += 1; break;
case 1: ret[i] -= 1; break;
}
if(ret[i] < '0') ret[i] = '9';
if(ret[i] > '9') ret[i] = '0';
return ret;
}
int openLock(vector<string>& deadends, string target) {
queue<Data> q;
unordered_set<string> h;
for(auto x: deadends) h.insert(x);
if(h.find("0000") != h.end()) return -1;
h.insert("0000");
q.push(Data("0000", 0));
while(!q.empty()){
Data cur = q.front();
if(cur.s == target) return cur.l;
for(int i = 0; i < 4; i++){
for(int k = 0; k < 2; k++){
string t = getS(cur.s, i, k);
if(h.find(t) != h.end()) continue;
h.insert(t);
q.push(Data(t, cur.l + 1));
}
}
q.pop();
}
return -1;
}
};
130. 被围绕的区域
class Solution {
public:
int n, m;
int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
void dfs(int i, int j, vector<vector<char>> &board){
board[i][j] = 'o';
for(int k = 0; k < 4; k++){
int x = i + dir[k][0];
int y = j + dir[k][1];
if(x < 0 || x >= n) continue;
if(y < 0 || y >= m) continue;
if(board[x][y] != 'O') continue;
dfs(x, y, board);
}
return ;
};
void solve(vector<vector<char>>& board) {
n = board.size(), m = board[0].size();
for(int i = 0; i < n; i++){
if(board[i][0] == 'O') dfs(i ,0, board);
if(board[i][m - 1] == 'O') dfs(i, m - 1, board);
}
for(int j = 0; j < m; j++){
if(board[0][j] == 'O') dfs(0, j, board);
if(board[n - 1][j] == 'O') dfs(n - 1, j, board);
}
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
if(board[i][j] == 'O') board[i][j] = 'X';
else if(board[i][j] == 'o') board[i][j] = 'O';
}
}
return;
}
};
494. 目标和
class Solution {
public:
int dfs(int i, int target, vector<int> &nums){
if(i == nums.size()){
return target == 0;
}
int ans = 0;
ans += dfs(i + 1, target - nums[i], nums); // +
ans += dfs(i + 1, target + nums[i], nums); // -
return ans;
}
int findTargetSumWays(vector<int>& nums, int target) {
return dfs(0, target, nums);
}
};
由于该程序效率太差,使用记忆化进行优化
数组和函数没有差别
class Solution {
public:
typedef pair<int, int> PII;
struct CMP {
int operator()(const PII &a) const {
return a.first ^ a.second;
}
};
unordered_map<PII, int, CMP> h;
int dfs(int i, int target, vector<int> &nums){
if(i == nums.size()){
return target == 0;
}
if(h.find(PII(i, target)) != h.end()){
return h[PII(i, target)];
}
int ans = 0;
ans += dfs(i + 1, target - nums[i], nums); // +
ans += dfs(i + 1, target + nums[i], nums); // -
h[PII(i, target)] = ans;
return ans;
}
int findTargetSumWays(vector<int>& nums, int target) {
h.clear();
return dfs(0, target, nums);
}
};
473. 火柴拼正方形
class Solution {
public:
bool dfs(int ind, vector<int> &arr, vector<int> &ms){
if(ind == -1) return true;
for(int i = 0; i < 4; i++){
if(arr[i] < ms[ind]) continue;
if(arr[i] == ms[ind] || arr[i] >= ms[ind] + ms[0]){
arr[i] -= ms[ind];
if(dfs(ind - 1, arr, ms)) return true;
arr[i] += ms[ind];
}
}
return false;
}
bool makesquare(vector<int>& matchsticks) {
sort(matchsticks.begin(), matchsticks.end());
vector<int> arr(4);
int sum = 0;
for(auto x : matchsticks) sum += x;
for(int i = 0; i < 4; i++) arr[i] = sum / 4;
return dfs(matchsticks.size() - 1, arr, matchsticks);
}
};
39. 组合总和
class Solution {
public:
void dfs(int ind, int target, vector<int> &nums, vector<int> &buff, vector<vector<int>> &ret){
if(target < 0) return;
if(target == 0){
ret.push_back(buff);
return;
}
if(ind == nums.size()) return;
dfs(ind + 1, target, nums, buff, ret);
buff.push_back(nums[ind]);
dfs(ind, target - nums[ind], nums, buff, ret);
buff.pop_back();
return;
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<int> buff;
vector<vector<int>> ret;
dfs(0, target, candidates, buff, ret);
return ret;
}
};