2021-03-13 Daily-Challenge
Today is Saturday, I gonna review the tasks I've done this week, and finish today's leetcode's March LeetCoding Challenge with cpp
.
LeetCode Review
Add to Array-Form of Integer
too easy to review
Guess Number Higher or Lower
too easy to review
Generate Random Point in a Circle
too easy to review
Remove Palindromic Subsequences
too easy to review
Add One Row to Tree
too easy to review
Integer to Roman
too easy to review
Coin Change
too easy to review
Check If a String Contains All Binary Codes of Size K
too easy to review
Find Servers That Handled Most Number of Requests
using pii = pair<int, int>;
class Solution {
public:
vector<int> busiestServers(int k, vector<int>& arrival, vector<int>& load) {
set<int> ok;
for(int i = 0; i < k; ++i) ok.insert(i);
priority_queue<pii, vector<pii>, greater<pii>> q;
vector<int> count(k);
int len = arrival.size();
for(int i = 0; i < len; ++i) {
while(!q.empty() && q.top().first <= arrival[i]) {
ok.insert(q.top().second);
q.pop();
}
if(ok.empty()) continue;
auto it = ok.lower_bound(i % k);
it = it == ok.end() ? ok.begin() : it;
int server = *it;
count[server] += 1;
ok.erase(server);
q.push(make_pair(arrival[i] + load[i], server));
}
int maxRequest = *max_element(count.begin(), count.end());
vector<int> answer;
for(int i = 0; i < k; ++i) if(count[i] == maxRequest) answer.push_back(i);
return answer;
}
};
Minimum Moves to Move a Box to Their Target Location
I try to optimize memory usage by using int to represent position, but get a far worse performance.
struct State {
char boxR;
char boxC;
char playerR;
char playerC;
};
struct Position {
char row;
char col;
};
constexpr State recover(int state) {
return State {
.boxR = char(state / 8000),
.boxC = char(state / 400 % 20),
.playerR = char(state / 20 % 20),
.playerC = char(state % 20),
};
}
constexpr Position position(int pos) {
return Position {
.row = char(pos / 20),
.col = char(pos % 20),
};
}
constexpr int calPos(int row, int col) {
return row * 20 + col;
}
const int moves[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
class Solution {
int rows;
int cols;
vector<int> checkMap(vector<vector<char>> &grid, int boxR, int boxC, int playerR, int playerC) {
unordered_set<int> vis;
queue<int> q;
q.push(calPos(playerR, playerC));
vis.insert(calPos(playerR, playerC));
int boxPos = calPos(boxR, boxC);
vector<int> pushes;
while(!q.empty()) {
auto [row, col] = position(q.front());
q.pop();
int diffRow = boxR - row;
int diffCol = boxC - col;
if(diffRow == 0 && abs(diffCol) == 1 && boxC + diffCol >= 0 && boxC + diffCol < cols && grid[boxR][boxC + diffCol] != '#') {
pushes.push_back(diffCol);
}
if(diffCol == 0 && abs(diffRow) == 1 && boxR + diffRow >= 0 && boxR + diffRow < rows && grid[boxR + diffRow][boxC] != '#') {
pushes.push_back(diffRow * 20);
}
for(int i = 0; i < 4; ++i) {
int newRow = row + moves[i][0];
int newCol = col + moves[i][1];
if(newRow < 0 || newRow >= rows || newCol < 0 || newCol >= cols || grid[newRow][newCol] == '#') continue;
int newPos = calPos(newRow, newCol);
if(vis.count(newPos) || newPos == boxPos) continue;
vis.insert(newPos);
q.push(newPos);
}
}
return move(pushes);
}
constexpr int applyPush(int state, int push) const {
int boxPos = state / 400;
int newBoxPos = boxPos + push;
return newBoxPos * 400 + boxPos;
}
public:
int minPushBox(vector<vector<char>>& grid) {
rows = grid.size();
cols = grid.front().size();
unordered_map<int, int> pushes;
int initState = 0;
int targetR = 0;
int targetC = 0;
for(int i = 0; i < rows; ++i) {
for(int j = 0; j < cols; ++j) {
if(grid[i][j] == 'T') {
targetR = i;
targetC = j;
grid[i][j] = '.';
} else if(grid[i][j] == 'B') {
initState += i * 8000 + j * 400;
grid[i][j] = '.';
} else if(grid[i][j] == 'S') {
initState += i * 20 + j;
grid[i][j] = '.';
}
}
}
queue<int> q;
q.push(initState);
pushes[initState] = 0;
while(!q.empty()) {
int state = q.front();
auto [boxR, boxC, playerR, playerC] = recover(state);
// cout << int(boxR) << ' ' << int(boxC) << ' ' << int(playerR) << ' ' << int(playerC) << endl;
q.pop();
if(boxR == targetR && boxC == targetC) return pushes[state];
auto validPushes = checkMap(grid, boxR, boxC, playerR, playerC);
for(auto validPush : validPushes) {
int newState = applyPush(state, validPush);
if(pushes.count(newState)) continue;
pushes[newState] = pushes[state] + 1;
q.push(newState);
}
}
return -1;
}
};
// 18 / 18 test cases passed.
// Status: Accepted
// Runtime: 188 ms
// Memory Usage: 46.8 MB
reuse unordered_set
using Position = pair<char, char>;
constexpr Position position(int pos) {
return make_pair(pos / 20, pos % 20);
}
constexpr int calPos(int row, int col) {
return row * 20 + col;
}
const int moves[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
class Solution {
int rows;
int cols;
vector<vector<char>> grid;
unordered_set<int> vis;
queue<int> q;
vector<int> checkMap(int boxR, int boxC, int playerR, int playerC) {
vis.clear();
q.push(calPos(playerR, playerC));
vis.insert(calPos(playerR, playerC));
int boxPos = calPos(boxR, boxC);
vector<int> pushes;
while(!q.empty()) {
auto [row, col] = position(q.front());
q.pop();
int diffRow = boxR - row;
int diffCol = boxC - col;
if(diffRow == 0 && abs(diffCol) == 1 && boxC + diffCol >= 0 && boxC + diffCol < cols && grid[boxR][boxC + diffCol] != '#') {
pushes.push_back(diffCol);
}
if(diffCol == 0 && abs(diffRow) == 1 && boxR + diffRow >= 0 && boxR + diffRow < rows && grid[boxR + diffRow][boxC] != '#') {
pushes.push_back(diffRow * 20);
}
for(int i = 0; i < 4; ++i) {
int newRow = row + moves[i][0];
int newCol = col + moves[i][1];
if(newRow < 0 || newRow >= rows || newCol < 0 || newCol >= cols || grid[newRow][newCol] == '#') continue;
int newPos = calPos(newRow, newCol);
if(vis.count(newPos) || newPos == boxPos) continue;
vis.insert(newPos);
q.push(newPos);
}
}
return pushes;
}
constexpr int applyPush(int state, int push) const {
int boxPos = state / 400;
int newBoxPos = boxPos + push;
return newBoxPos * 400 + boxPos;
}
public:
int minPushBox(vector<vector<char>>& grid) {
rows = grid.size();
cols = grid.front().size();
unordered_map<int, int> pushes;
this->grid = grid;
int initState = 0;
int targetR = 0;
int targetC = 0;
for(int i = 0; i < rows; ++i) {
for(int j = 0; j < cols; ++j) {
if(grid[i][j] == 'T') {
targetR = i;
targetC = j;
grid[i][j] = '.';
} else if(grid[i][j] == 'B') {
initState += i * 8000 + j * 400;
grid[i][j] = '.';
} else if(grid[i][j] == 'S') {
initState += i * 20 + j;
grid[i][j] = '.';
}
}
}
queue<int> q;
q.push(initState);
pushes[initState] = 0;
while(!q.empty()) {
int state = q.front();
int boxR = state / 8000;
int boxC = state / 400 % 20;
int playerR = state / 20 % 20;
int playerC = state % 20;
// cout << int(boxR) << ' ' << int(boxC) << ' ' << int(playerR) << ' ' << int(playerC) << endl;
q.pop();
if(boxR == targetR && boxC == targetC) return pushes[state];
auto validPushes = checkMap(boxR, boxC, playerR, playerC);
for(auto validPush : validPushes) {
int newState = applyPush(state, validPush);
if(pushes.count(newState)) continue;
pushes[newState] = pushes[state] + 1;
q.push(newState);
}
}
return -1;
}
};
// 18 / 18 test cases passed.
// Status: Accepted
// Runtime: 176 ms
// Memory Usage: 30.1 MB
maybe I need to run some profile to get reason...
March LeetCoding Challenge 13
Description
Binary Trees With Factors
Given an array of unique integers, arr
, where each integer arr[i]
is strictly greater than 1
.
We make a binary tree using these integers, and each number may be used for any number of times. Each non-leaf node's value should be equal to the product of the values of its children.
Return the number of binary trees we can make. The answer may be too large so return the answer modulo 109 + 7
.
Example 1:
Input: arr = [2,4]
Output: 3
Explanation: We can make these trees: [2], [4], [4, 2, 2]
Example 2:
Input: arr = [2,4,5,10]
Output: 7
Explanation: We can make these trees: [2], [4], [5], [10], [4, 2, 2], [10, 2, 5], [10, 5, 2].
Constraints:
1 <= arr.length <= 1000
- $2 \le arr[i] \le 10^9$
Solution
const int MOD = 1e9 + 7;
class Solution {
public:
int numFactoredBinaryTrees(vector<int>& arr) {
sort(arr.begin(), arr.end());
int len = arr.size();
vector<int> count(len, 1);
for(int i = 1; i < len; ++i) {
for(int j = 0; arr[i] / arr[j] >= arr[j]; ++j) {
if(arr[i] % arr[j]) continue;
int pos = lower_bound(arr.begin(), arr.end(), arr[i] / arr[j]) - arr.begin();
if(arr[i] / arr[j] != arr[pos]) continue;
count[i] += (2LL - (arr[j] == arr[pos])) * count[j] * count[pos] % MOD;
count[i] %= MOD;
}
}
int answer = accumulate(count.begin(), count.end(), 0, [](int prev, int cur) {
return (prev + cur) % MOD;
});
return answer;
}
};
// 47 / 47 test cases passed.
// Status: Accepted
// Runtime: 36 ms
// Memory Usage: 8.2 MB
// Runtime: 32 ms, faster than 100.00% of C++ online submissions for Binary Trees With Factors.
// Memory Usage: 8.1 MB, less than 100.00% of C++ online submissions for Binary Trees With Factors.