Commit d2dfd695 authored by anqiwa's avatar anqiwa 😲
Browse files

8/23/21 update

parent 17894f13
/*
* @lc app=leetcode id=131 lang=cpp
*
* [131] Palindrome Partitioning
*/
// @lc code=start
class Solution
{
bool dp[16][16];
vector<vector<string>> res;
public:
vector<vector<string>> partition(string s)
{
// this problem has two parts:
// 1. use dp to record if [i:j] is palindrome (O(n^2))
// 2. dfs(2^n)
const int n = s.size();
// do the dp
// rescursive relation:
// dp[i][j] = s[i] == (s[j] && dp[i+1][j-1] == true)
// do for the range len == 1
for (int i = 0; i < n; i++)
dp[i][i] = true;
for (int i = 0; i + 1 < n; i++)
dp[i][i + 1] = s[i] == s[i + 1];
for (int len = 3; len <= n; len++)
for (int i = 0; i + len - 1 < n; i++)
{
int j = i + len - 1;
if (s[i] == s[j])
dp[i][j] = dp[i + 1][j - 1];
else
dp[i][j] = false;
}
// do dfs
vector<string> ans; // curr paritioning
int curr = 0;
dfs(s, curr, ans);
return res;
}
void dfs(string &s, int curr, vector<string> &ans)
{
const int n = s.size();
if (curr == n)
{
res.push_back(ans);
return;
}
for (int j = curr; j < n; ++j)
{
if (dp[curr][j])
{
ans.push_back(s.substr(curr, j - curr + 1));
dfs(s, j + 1, ans);
ans.pop_back();
}
} //for
}
};
// @lc code=end
/*
* @lc app=leetcode id=200 lang=cpp
*
* [200] Number of Islands
*/
// @lc code=start
class Solution
{
vector<pair<int, int>> dirs = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
public:
int numIslands(vector<vector<char>> &grid)
{
// either bfs ad dfs works
// this is the bfs solution
const int m = grid.size();
if (m == 0)
return 0;
const int n = grid[0].size();
int count = 0;
// find the next 1
for (int i = 0; i < m; ++i)
{
for (int j = 0; j < n; ++j)
{
if (grid[i][j] == '1')
{
count += 1;
//do bfs here
queue<pair<int, int>> q; //{pos}
q.push({i, j});
grid[i][j] = '#';
while (!q.empty())
{
auto [curr_x, curr_y] = q.front();
q.pop();
for (auto &dir : dirs)
{
int n_x = curr_x + dir.first;
int n_y = curr_y + dir.second;
if (n_x < 0 || n_y < 0 || n_x >= m || n_y >= n)
continue;
if (grid[n_x][n_y] != '1')
continue;
q.push({n_x, n_y});
grid[n_x][n_y] = '#';
} //for
} //while
}
} //for
} //for
return count;
}
};
// @lc code=end
class Solution
{
// for bijective mapping, need two maps
unordered_map<char, string> map1;
unordered_map<string, char> map2;
public:
bool wordPatternMatch(string pattern, string s)
{
int curr = 0;
int currInPat = 0;
return dfs(pattern, s, curr, currInPat);
}
bool dfs(string &pattern,
string &s,
int curr, int currInPat)
{
if (curr == s.size() &&
currInPat == pattern.size())
return true;
char ch = pattern[currInPat];
if (map1.find(ch) != map1.end())
{
string t = map1[ch];
if (curr + t.size() > s.size())
return false;
if (s.substr(curr, t.size()) != t)
return false;
return dfs(pattern, s, curr + t.size(), currInPat + 1);
}
else
{
char ch = pattern[currInPat];
for (int i = curr; i < s.size(); ++i)
{
string t = s.substr(curr, i - curr + 1);
if (map2.find(t) != map2.end())
continue;
map2[t] = ch;
map1[ch] = t;
if (dfs(pattern, s, curr + t.size(), currInPat + 1))
return true;
map1.erase(ch);
map2.erase(t);
} //for
}
return false;
}
};
\ No newline at end of file
/*
* @lc app=leetcode id=310 lang=cpp
*
* [310] Minimum Height Trees
*/
// @lc code=start
class Solution
{
public:
vector<int> findMinHeightTrees(int n, vector<vector<int>> &edges)
{
// 类似于拓扑排序的做法
// 选叶子节点, 从外网里面拨洋葱
if (n == 1)
return {0};
if (n == 2)
return {0, 1};
vector<int> res;
// adj list and 出度
unordered_map<int, int> Degree;
unordered_map<int, vector<int>> Up;
for (auto &edge : edges)
{
Degree[edge[0]]++;
Degree[edge[1]]++;
Up[edge[1]].push_back(edge[0]);
Up[edge[0]].push_back(edge[1]);
}
queue<int> q;
for (auto &a : Degree)
if (a.second == 1)
q.push(a.first);
int count = 0;
while (!q.empty())
{
int k = q.size();
for (int i = 0; i < k; i++)
{
int node = q.front();
q.pop();
count++;
for (auto upNode : Up[node])
{
Degree[upNode]--;
if (Degree[upNode] == 1)
q.push(upNode);
}
}
if (count + q.size() == n)
{
while (!q.empty())
{
res.push_back(q.front());
q.pop();
}
return res;
}
}
return res;
}
};
// @lc code=end
/*
* @lc app=leetcode id=39 lang=cpp
*
* [39] Combination Sum
*/
// @lc code=start
class Solution
{
vector<int> currList;
public:
vector<vector<int>> combinationSum(vector<int> &candidates, int target)
{
const int n = candidates.size();
int curr = 0;
vector<vector<int>> res;
sort(candidates.begin(), candidates.end());
dfs(candidates, curr, target, res);
return res;
}
void dfs(vector<int> &candidates,
int curr,
int target,
vector<vector<int>> &res)
{
if (target == 0)
{
res.push_back(currList);
return;
}
for (int i = curr; i < candidates.size(); ++i)
{
if (candidates[i] > target)
break;
currList.push_back(candidates[i]);
dfs(candidates, i, target - candidates[i], res);
currList.pop_back();
} //for
}
};
// @lc code=end
/*
* @lc app=leetcode id=40 lang=cpp
*
* [40] Combination Sum II
*/
// @lc code=start
class Solution
{
vector<int> currList;
public:
vector<vector<int>> combinationSum2(vector<int> &candidates, int target)
{
int n = candidates.size();
int curr = 0;
vector<vector<int>> res;
sort(candidates.begin(), candidates.end());
dfs(candidates, curr, target, res);
return res;
}
void dfs(vector<int> &candidates,
int curr,
int target,
vector<vector<int>> &res)
{
if (0 == target)
{
res.push_back(currList);
return;
}
if (target < 0)
return;
for (int i = curr; i < candidates.size(); ++i)
{
// 精髓: disallow samw number in the same depth
if (i > curr && candidates[i] == candidates[i - 1])
continue;
currList.push_back(candidates[i]);
dfs(candidates, i + 1,
target - candidates[i], res);
currList.pop_back();
} //for
}
};
// @lc code=end
/*
* @lc app=leetcode id=407 lang=cpp
*
* [407] Trapping Rain Water II
*/
// @lc code=start
using VI = vector<int>;
class Solution
{
vector<pair<int, int>> dirs = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
public:
int trapRainWater(vector<vector<int>> &heightMap)
{
const int m = heightMap.size();
const int n = heightMap[0].size();
//用 Dijktra 想成海水从四周溢进来
priority_queue<VI, vector<VI>, greater<>> pq; // min heap
vector<vector<bool>> visited(m, vector<bool>(n, false));
int res = 0;
// add 4 borders
for (int i = 0; i < m; ++i)
{
for (int j = 0; j < n; ++j)
{
if (i == 0 || i == m - 1 || j == 0 || j == n - 1)
{
pq.push({heightMap[i][j], i, j});
visited[i][j] = true;
}
} //for
} //for
int curr = INT_MIN;
while (!pq.empty())
{
int h = pq.top()[0];
int x = pq.top()[1];
int y = pq.top()[2];
pq.pop();
if (h > curr)
curr = h;
res += curr - h;
for (int k = 0; k < 4; k++)
{
int i = x + dirs[k].first;
int j = y + dirs[k].second;
if (i < 0 || i >= m || j < 0 || j >= n)
continue;
if (visited[i][j])
continue;
visited[i][j] = 1;
pq.push({heightMap[i][j], i, j});
}
}
return res;
}
};
// @lc code=end
/*
* @lc app=leetcode id=52 lang=cpp
*
* [52] N-Queens II
*/
// @lc code=start
class Solution
{
public:
int totalNQueens(int n)
{
// dfs: each row has n place to put the queen
int res = 0;
vector<vector<char>> grid(n, vector<char>(n, '.'));
dfs(grid, res, 0);
return res;
}
void dfs(vector<vector<char>> &grid, int &res, int x)
{
if (x == grid.size())
{
++res;
return;
}
for (int y = 0; y < grid.size(); ++y)
{
if (isValid(grid, x, y))
{
grid[x][y] = 'Q';
dfs(grid, res, x + 1);
grid[x][y] = '.';
}
}
}
bool isValid(vector<vector<char>> &grid, int x, int y)
{
for (int row = 0; row < grid.size(); ++row)
if (row != x && grid[row][y] == 'Q')
return false;
for (int col = 0; col < grid.size(); ++col)
if (col != y && grid[x][col] == 'Q')
return false;
// only need to check leftUpper and rightUpper
int k = 1;
while (x - k >= 0 && y - k >= 0)
{
int row = x - k;
int col = y - k;
if (grid[row][col] == 'Q')
return false;
++k;
}
k = 1;
while (x - k >= 0 && y + k < grid.size())
{
int row = x - k;
int col = y + k;
if (grid[row][col] == 'Q')
return false;
++k;
}
return true;
}
};
// @lc code=end
/*
* @lc app=leetcode id=743 lang=cpp
*
* [743] Network Delay Time
*/
// @lc code=start
class Solution
{
public:
int networkDelayTime(vector<vector<int>> &times, int n, int k)
{
// Dijkstra
unordered_map<int, vector<pair<int, int>>> graph; //{src, {time, next}}
for (auto &t : times)
graph[t[0]].push_back({t[2], t[1]});
priority_queue<pair<int, int>,
vector<pair<int, int>>, greater<>>
pq; // min heap
int res = 0;
vector<bool> visited(n + 1, false);
pq.push({0, k});
int count = 0;
while (!pq.empty())
{
auto [dis, curr] = pq.top();
pq.pop();
// idea: the first pop is the shortest path from k
if (visited[curr])
continue;
count++;
visited[curr] = true;
res = max(res, dis);
for (auto &next : graph[curr])
pq.push({dis + next.first, next.second});
} //while
//cout << count << endl;
if (count == n)
return res;
return -1;
}
};
// @lc code=end
/*
* @lc app=leetcode id=778 lang=cpp
*
* [778] Swim in Rising Water
*/
// @lc code=start
using VI = vector<int>;
class Solution
{
vector<pair<int, int>> dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
public:
int swimInWater(vector<vector<int>> &grid)
{
const int n = grid.size();
int res = 0;
priority_queue<VI, vector<VI>, greater<>> pq;
vector<vector<bool>> visited(n, vector<bool>(n, false));
pq.push({grid[0][0], 0, 0});
while (!pq.empty())
{
int h = pq.top()[0];
int x = pq.top()[1];
int y = pq.top()[2];
res = max(res, h);
pq.pop();
if (visited[x][y])
continue;
visited[x][y] = 1;
if (x == n - 1 && y == n - 1)
return res;
for (int k = 0; k < 4; k++)
{
int xx = x + dirs[k].first;
int yy = y + dirs[k].second;
if (xx < 0 || xx >= n || yy < 0 || yy >= n)
continue;
if (visited[xx][yy] == 1)
continue;
pq.push({grid[xx][yy], xx, yy});
}
} //while
return -1;
}
};
// @lc code=end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment