#include <iostream>
#include <sstream>
#include <queue>
#include <string>
#include <unordered_set>
#include <unordered_map>
using namespace std;
struct TreeNode
{
TreeNode(int v):val(v){}
int val = 0;
TreeNode* left = nullptr;
TreeNode* right = nullptr;
};
void print(TreeNode* root)
{
if(nullptr == root)return ;
cout << root->val << endl;
print(root->left);
print(root->right);
return;
}
int minDepth(TreeNode* root)
{
if(nullptr == root)return 0;
queue<TreeNode*>q;
int depth = 1;
q.push(root);
while(!q.empty())
{
int size = q.size();
for(int i = 0; i < size; ++i)
{
TreeNode* cur = q.front();
q.pop();
if(cur->left == nullptr && cur->right == nullptr)return depth;
if(cur->left)q.push(cur->left);
if(cur->right)q.push(cur->right);
}
++depth;
}
return depth;
}
int minDepth_r(TreeNode* root)
{
if(nullptr == root)return 0;
if(root->left == nullptr)return minDepth_r(root->right) + 1;
if(root->right == nullptr)return minDepth_r(root->left) + 1;
return min(minDepth_r(root->left),minDepth_r(root->right)) + 1;
}
vector<vector<int>>levelOrder(TreeNode* root)
{
vector<vector<int>>res;
queue<TreeNode*>q;
if(root == nullptr)return {};
q.push(root);
while(!q.empty())
{
vector<int>v;
int size = q.size();
for(int i = 0; i < size; ++i)
{
TreeNode* cur = q.front();
q.pop();
v.emplace_back(cur->val);
if(cur->left)q.push(cur->left);
if(cur->right)q.push(cur->right);
}
res.emplace_back(v);
}
return res;
}
void dfs(TreeNode* root, vector<vector<int>>& res, int height)
{
if(nullptr == root)return;
vector<int>t;
if(height >= res.size())res.emplace_back(t);
res[height].emplace_back(root->val);
if(root->left)dfs(root->left,res,height + 1);
if(root->right)dfs(root->right,res,height + 1);
return ;
}
vector<vector<int>>levelOrderDFS(TreeNode* root)
{
vector<vector<int>>res;
if(nullptr == root) return {};
dfs(root,res,0);
return res;
}
void print(const vector<vector<int>>&nums)
{
for(auto num : nums)
{
for(auto n : num)
{
cout << n << " ";
}
cout << endl;
}
}
int ladderLength(string beginWord,string endWord, const vector<string>& wordList)
{
unordered_set<string>set;
for(auto word : wordList)
{
set.insert(word);
}
queue<string>q;
q.push(beginWord);
int n = beginWord.size(),step = 1;
while(!q.empty())
{
int size = q.size();
for(int i = 0; i < size; ++i)
{
string cur = q.front();
q.pop();
if(cur == endWord)return step;
for(int j = 0; j < n; ++j)
{
for(char c = 'a'; c <= 'z'; ++c)
{
string next = cur;
next[j] = c;
if(set.count(next))
{
if(next == endWord)return step + 1;
set.erase(next);
q.push(next);
}
}
}
}
++step;
}
return 0;
}
int ladderLength_BFS(string begWord, string endWord, const vector<string>& wordList)
{
unordered_set<string>begSet,endSet,visitedSet,wordSet;
for(string str: wordList)
{
wordSet.insert(str);
}
if(!wordSet.count(endWord))return 0;
int step = 1, n = begWord.size();
begSet.insert(begWord);
endSet.insert(endWord);
while(!begSet.empty() && !endSet.empty())
{
unordered_set<string>nextSet;
for(string str:begSet)
{
for(int i = 0; i < n; ++i)
{
for(char c = 'a'; c <= 'z'; ++c)
{
char pre = str[i];
string next = str;
next[i] = c;
if(endSet.count(next))return step + 1;
visitedSet.insert(next);
if(wordSet.count(next))
{
nextSet.insert(next);
}
next[i] = pre;
}
}
}
if(endSet.size() < nextSet.size())
{
begSet = endSet;
endSet = nextSet;
}
else
{
begSet = nextSet;
}
++step;
}
return 0;
}
vector<vector<int>>dirs{{0,1},{0,-1},{-1,0},{1,0}};
bool hasPath(const vector<vector<int>>&maze, const vector<int>& start, const vector<int>& des)
{
int m = maze.size(), n = maze[0].size();
vector<vector<bool>>visited(m,vector<bool>(n,false));
queue<vector<int>>q;
q.push(start);
while(!q.empty())
{
auto cur = q.front();
q.pop();
if(cur[0] == des[0] && cur[1] == des[1])return true;
for(auto dir:dirs)
{
int x = dir[0] + cur[0], y = dir[1] + cur[1];
while(x >= 0 && y >= 0 && x < m && y < n && maze[x][y] == 0)
{
x += dir[0];
y += dir[1];
}
x -= dir[0];
y -= dir[1];
if(!visited[x][y])
{
q.push({x,y});
visited[x][y] = true;
}
}
}
return false;
}
void dijlstra(const vector<vector<int>>& maze, const vector<int>&start,vector<vector<int>>&distance)
{
priority_queue<vector<int>>q;
q.push({start[0],start[1],0});
while(!q.empty())
{
auto cur = q.top();
q.pop();
for(auto dir:dirs)
{
int x = cur[0] + dir[0];
int y = cur[1] + dir[1];
int cnt = 0;
while(x >= 0 && y >= 0 && x < maze.size() && y < maze[0].size() && maze[x][y]== 0)
{
x += dir[0];
y += dir[1];
++cnt;
}
x -= dir[0];
y -= dir[1];
if(distance[cur[0]][cur[1]]+cnt < distance[x][y])
{
distance[x][y] = distance[cur[0]][cur[1]]+cnt;
q.push({x,y,distance[x][y]});
}
}
}
}
int shortestDistance(const vector<vector<int>>&maze,const vector<int>&start, const vector<int>& end)
{
int m = maze.size(), n = maze[0].size();
vector<vector<int>>distance(m,vector<int>(n,INT_MAX));
distance[start[0]][start[1]] = 0;
dijlstra(maze,start,distance);
return distance[end[0]][end[1]] == INTMAX_MAX ? -1 : distance[end[0]][end[1]];
}
bool canFinish(int numCourses,const vector<vector<int>>& prerequists)
{
unordered_map<int,vector<int>>map;
vector<int>indegree(numCourses);
for(int i = 0; i < prerequists.size(); ++i)
{
int end = prerequists[i][0],start = prerequists[i][1];
map[start].emplace_back(end);
++indegree[end];
}
queue<int>q;
for(int i = 0; i < indegree.size(); ++i)
{
if(indegree[i] == 0)
{
q.push(i);
}
}
int cnt = 0;
while(!q.empty())
{
int cur = q.front();
q.pop();
++cnt;
if(map.find(cur)!=map.end())
{
for(int num : map.at(cur))
{
if(--indegree[num] == 0)q.push(num);
}
}
}
return cnt == numCourses;
}
int openLock(vector<string>& deadends, string target) {
if (target == "0000") {
return 0;
}
unordered_set<string> dead(deadends.begin(), deadends.end());
if (dead.count("0000")) {
return -1;
}
auto num_prev = [](char x) -> char {
return (x == '0' ? '9' : x - 1);
};
auto num_succ = [](char x) -> char {
return (x == '9' ? '0' : x + 1);
};
// 枚举 status 通过一次旋转得到的数字
auto get = [&](string& status) -> vector<string> {
vector<string> ret;
for (int i = 0; i < 4; ++i) {
char num = status[i];
status[i] = num_prev(num);
ret.push_back(status);
status[i] = num_succ(num);
ret.push_back(status);
status[i] = num;
}
return ret;
};
queue<pair<string, int>> q;
q.emplace("0000", 0);
unordered_set<string> seen = {"0000"};
while (!q.empty()) {
auto cur = q.front();
string status = cur.first;
int step = cur.second;
q.pop();
for (auto&& next_status: get(status)) {
if (!seen.count(next_status) && !dead.count(next_status)) {
if (next_status == target) {
return step + 1;
}
q.emplace(next_status, step + 1);
seen.insert(move(next_status));
}
}
}
return -1;
}
int main()
{
//LeetCode111
TreeNode t1(3);
TreeNode t2(9);
TreeNode t3(20);
TreeNode t4(15);
TreeNode t5(7);
t1.left = &t2;
t1.right = &t3;
t3.left = &t4;
t3.right = &t5;
// print(&t1);
cout << minDepth(&t1) << endl;
cout << minDepth_r(&t1) << endl;
//LeetCode102
print(levelOrder(&t1));
print(levelOrderDFS(&t1));
//LeetCode127
string begWord = "hit", endWord = "cog";
vector<string>WordList{"hot","dot","dog","lot","log","cog"};
cout << ladderLength(begWord,endWord,WordList) << endl;
cout << ladderLength_BFS(begWord,endWord,WordList) << endl;
//LeetCode752
vector<string>deadends{"0201","0101","0102","1212","2002"};
string target = "0202";
cout << openLock(deadends,target) << endl;
//LeetCode490
vector<vector<int>>maze{{0,0,1,0,0},{0,0,0,0,0},{0,0,0,1,0},{1,1,0,1,1},{0,0,0,0,0}};
vector<int>start{0,4},destination{4,4};
cout << hasPath(maze,start,destination) << endl;
//LeetCode505
cout << shortestDistance(maze,start,destination) <<endl;
//LeetCode207
int numCourses = 2;
vector<vector<int>>prerequistes{{1,0},{0,1}};
cout << canFinish(numCourses,prerequistes) << endl;
return 0;
}