Algorithms & Data Structures : Array Problems

吳建興
22 min readJul 23, 2022

--

Problems

LeetCode 56. Merge Intervals

LeetCode 2016. Maximum Difference Between Increasing Elements

LeetCode 2013. Detect Squares

LeetCode 2018. Check if Word Can Be Placed In Crossword

LeetCode 1182. Shortest Distance to Target Color
[Array]

LeetCode 251. Flatten 2D Vector
[Array]

LeetCode : 2268. Minimum Number of Keypresses
[Array]

LeetCode : 2257. Count Unguarded Cells in the Grid
[Array]

LeetCode : 1424. Diagonal Traverse II
[Array][sorting]

LeetCode : 2087. Minimum Cost Homecoming of a Robot in a Grid
[Array][Greedy]

LeetCode : 2201. Count Artifacts That Can Be Extracted
[Array][hash table]

LeetCode : 2274. Maximum Consecutive Floors Without Special Floors
[array][sorting]

LeetCode : 1855. Maximum Distance Between a Pair of Values
[array][two-pointers]

LeetCode : 2105. Watering Plants II
[array][two-pointers]

LeetCode : 1438. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit
[array][ordered set][monotonic queue]

LeetCode : 2012. Sum of Beauty in the Array
[array][dynamic programming]

LeetCode : 2261. K Divisible Elements Subarrays
[array][trie]

LeetCode : 2365. Task Scheduler II
[Array][Simulation][Hash Table]

LeetCode : 848. Shifting Letters
[Array][String]

LeetCode : 822. Card Flipping Game
[Array]

LeetCode : 2391. Minimum Amount of Time to Collect Garbage
[Array]

LeetCode : 1868. Product of Two Run-Length Encoded Arrays
[Array][Two Pointers]

LeetCode : 1060. Missing Element in Sorted Array
[Array][Binary Search]

LeetCode : 2061. Number of Spaces Cleaning Robot Cleaned
[Array][Simulation][Matrix]

LeetCode : 2405. Optimal Partition of String
[Array]

LeetCode : 2270. Number of Ways to Split Array
[Array][Prefix Sum]

LeetCode : 2090. K Radius Subarray Averages
[Array][Sliding Window]

LeetCode : 218. The Skyline Problem
[Hard][Array][Line Sweep][Divide and Conquer]
[Binary Indexed Tree][Segment Tree][Heap ( Priority Queue )]
[Ordered Set]

LeetCode : 2424. Longest Uploaded Prefix
[Array][Binary Search][Union Find][Design]
[Binary Indexed Tree][Segment Tree]
[Heap (Priority Queue)][Ordered Set]

LeetCode : 16. 3Sum Closest
[Array][Two Pointers][Sorting]

LeetCode : 334. Increasing Triplet Subsequence
[Array][Greedy]

LeetCode : 1995. Count Special Quadruplets
[Array]

LeetCode : 2462. Total Cost to Hire K Workers
[Array][Two Pointers][Heap (Priority Queue)][Ordered Map]

LeetCode : 2078. Two Furthest Houses With Different Colors
[Array][Greedy]

LeetCode : 2210. Count Hills and Valleys in an Array
[Array]

LeetCode : 2229. Check if an Array Is Consecutive
[Array]

LeetCode : 2482. Difference Between Ones and Zeros in Row and Column
[Array]

LeetCode : 2350. Shortest Impossible Sequence of Rolls
[Array][Greedy][Hash Table][Hard]

LeetCode : 2502. Design Memory Allocator
[Array]

LeetCode : 2511. Maximum Enemy Forts That Can Be Captured
[Easy][Array]

LeetCode : 2555. Maximize Win From Two Segments
[Medium][Array][Queue][Sliding Window][Binary Search]

LeetCode 56. Merge Intervals

假如有重疊,就記下左邊界與右邊界
假如不重疊,就將紀錄的左邊界與右邊界丟到 vector裡

class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
vector<vector<int>> res;
vector<vector<int>> sorted = intervals;
sort(sorted.begin(), sorted.end());

int minVal = INT_MAX;
int maxVal = INT_MIN;
for(int i = 0;i < sorted.size();i++) {
if(minVal == INT_MAX) {
minVal = sorted[i][0];
maxVal = sorted[i][1];
} else {
if(maxVal >= sorted[i][0]) {
// overlap
minVal = min(minVal, sorted[i][0]);
maxVal = max(maxVal, sorted[i][1]);
} else {
res.push_back({minVal, maxVal});
minVal = sorted[i][0];
maxVal = sorted[i][1];
}
}
}

if(res.size() == 0 || res.back()[0] != minVal) {
res.push_back({minVal, maxVal});
}

return res;
}
};

LeetCode 2016. Maximum Difference Between Increasing Elements

由右往左,一邊紀錄當前最大值,一邊求解。

class Solution {
public:
int maximumDifference(vector<int>& nums) {
int res = -1;
int maxVal = INT_MIN;
for(int i = nums.size() - 1;i >= 0;i--) {
if(maxVal != INT_MIN && maxVal != nums[i]) {
res = max(res, maxVal - nums[i]);
}
maxVal = max(maxVal, nums[i]);
}
return res;
}
};

LeetCode 2013. Detect Squares

無腦暴力解… 所以效能很差。
TODO : 優化看看,或是看其他人怎麼解

class DetectSquares {
private:
vector<vector<int>> panel;
public:

DetectSquares() {
panel = vector<vector<int>>(1001, vector<int>(1001, 0));
}

void add(vector<int> point) {
panel[point[0]][point[1]]++;
}

int count(vector<int> point) {
int ans = 0;
for(int i = 0;i < panel.size();i++) {
if(i == point[0]) {
continue;
}

if(panel[i][point[1]] > 0) {
int len = i - point[0];
// Upper
if(point[1] + abs(len) <= 1000 &&
panel[i][point[1] + abs(len)] > 0 &&
panel[point[0]][point[1] + abs(len)] > 0) {
int tmp = 1;
tmp *= panel[i][point[1]];
tmp *= panel[i][point[1] + abs(len)];
tmp *= panel[point[0]][point[1] + abs(len)];
ans += tmp;
}

// Lower
if(point[1] - abs(len) >= 0 &&
panel[i][point[1] - abs(len)] > 0 &&
panel[point[0]][point[1] - abs(len)] > 0) {
int tmp = 1;
tmp *= panel[i][point[1]];
tmp *= panel[i][point[1] - abs(len)];
tmp *= panel[point[0]][point[1] - abs(len)];
ans += tmp;
}
}
}
return ans;
}
};
/**
* Your DetectSquares object will be instantiated and called as such:
* DetectSquares* obj = new DetectSquares();
* obj->add(point);
* int param_2 = obj->count(point);
*/

LeetCode 2018. Check if Word Can Be Placed In Crossword

簡而言之就是暴力解。

TODO : 在複雜度上理應會 TLE,看有沒有辦法壓低複雜度,或是參考別人的寫法。

// 只有最端點的格子需要進行字串的比對
// 1. 遍尋所有格子,找出每一個端點,以及字串可進行比對的方向
// 2. 就每個可比對的格子,以及其方向進行比對
typedef enum {
UP,
DOWN,
LEFT,
RIGHT
} DIRECTION;
class Solution {
private:
//
int X[4] = {-1, 1, 0, 0};
int Y[4] = {0, 0, -1, 1};
public:
bool placeWordInCrossword(vector<vector<char>>& board, string word) {
for(int i = 0;i < board.size();i++) {
for(int j = 0;j < board[0].size();j++) {
if('#' != board[i][j]) {
for(int q = 0;q < 4;q++) {
int newx = i + X[q];
int newy = j + Y[q];
int tmpx = i;
int tmpy = j;
if(newx >= board.size() || newx < 0 ||
newy >= board[0].size() || newy < 0 ||
'#' == board[newx][newy]) {

int num = 0;
while(tmpx >= 0 && tmpx < board.size() &&
tmpy >= 0 && tmpy < board[0].size() &&
'#' != board[tmpx][tmpy]) {

if(num == word.size()) {
// 空格超出字串長度
// 故意把 num 用錯
num = -1;
break;
}

if(' ' == board[tmpx][tmpy] ||
word[num] == board[tmpx][tmpy]) {
num++;
} else {
num = -1;
break;
}

if(UP == q) {
// 字串要往 DOWN 的方向進行比對
tmpx += X[DOWN];
tmpy += Y[DOWN];
} else if(DOWN == q) {
// 字串要往 UP 的方向進行比對
tmpx += X[UP];
tmpy += Y[UP];
} else if(LEFT == q) {
// 字串要往 RIGHT 的方向進行比對
tmpx += X[RIGHT];
tmpy += Y[RIGHT];
} else if(RIGHT == q) {
// 字串要往 LEFT 的方向進行比對
tmpx += X[LEFT];
tmpy += Y[LEFT];
}
}

if(num == word.size()) {
return true;
}
}

}
}
}
}

return false;
}
};

LeetCode 1182. Shortest Distance to Target Color

由左往右處理一次,再由右往左處理一次。

class Solution {
public:
vector<int> shortestDistanceColor(vector<int>& colors, vector<vector<int>>& queries) {
vector<int> v;
vector<vector<int>> rec = vector<vector<int>>(colors.size(), vector<int>(3, -1));
vector<int> tmp = vector<int>(3, -1);


for(int i = 0;i < colors.size();i++) {
for(int j = 0;j < tmp.size();j++) {
if(-1 == tmp[j]) {

} else {
tmp[j]++;
}
if(colors[i % colors.size()] - 1 == j) {
tmp[j] = 0;
}
}

for(int j = 0;j < tmp.size();j++) {
if(-1 != tmp[j]) {
if(-1 == rec[i][j]) {
rec[i][j] = tmp[j];
} else {
rec[i][j] = min(rec[i][j], tmp[j]);
}
}
}

}

for(int i = colors.size() - 1;i >= 0;i--) {
for(int j = 0;j < tmp.size();j++) {
if(-1 == tmp[j]) {

} else {
tmp[j]++;
}
if(colors[i] - 1 == j) {
tmp[j] = 0;
}
}

for(int j = 0;j < tmp.size();j++) {
if(-1 != tmp[j]) {
if(-1 == rec[i][j]) {
rec[i][j] = tmp[j];
} else {
rec[i][j] = min(rec[i][j], tmp[j]);
}
}
}
}

for(int i = 0;i < queries.size();i++) {
v.push_back(rec[queries[i][0]][queries[i][1] - 1]);
}

return v;
}
};

LeetCode 251. Flatten 2D Vector

其實不太確定我的實作有沒有符合題目要求 XD。

// TODO 使用 C++ 的 iterator 來解這一題class Vector2D {
private:
vector<int> v;
int index = 0;
public:
Vector2D(vector<vector<int>>& vec) {
for(int i = 0;i < vec.size();i++) {
for(int j = 0;j < vec[i].size();j++) {
v.push_back(vec[i][j]);
}
}
}

int next() {
return v[index++];
}

bool hasNext() {
return index != v.size();
}
};
/**
* Your Vector2D object will be instantiated and called as such:
* Vector2D* obj = new Vector2D(vec);
* int param_1 = obj->next();
* bool param_2 = obj->hasNext();
*/

LeetCode : 2268. Minimum Number of Keypresses

typedef struct Node Node;
struct Node {
char c;
int n;
};
class Solution {
public:
// 把頻率最高的字元放在第一個,最多能有 9 個字元在第一個位置
// 於是照著頻率排序後,每九個字元就把 val += 1
int minimumKeypresses(string s) {
vector<Node> v = vector<Node>(26, { 0 });

for(int i = 0;i < s.size();i++) {
v[s[i] - 'a'].c = s[i];
v[s[i] - 'a'].n++;
}

sort(v.begin(), v.end(), [](Node &a, Node &b) {
return a.n > b.n;
});

int num = 0;
int val = 1;
int ans = 0;
for(int i = 0;i < v.size();i++) {
if(v[i].n > 0) {
ans += val * v[i].n;
num++;
if(9 == num) {
val++;
num = 0;
}
}
}

return ans;
}
};

LeetCode : 2257. Count Unguarded Cells in the Grid

// 整個 grid 遍尋三次
class Solution {
public:
int countUnguarded(int m, int n, vector<vector<int>>& guards, vector<vector<int>>& walls) {
// G ==> 'G'
// W ==> 'W'
// 0 ==> not visited
// 1 ==> visited
vector<vector<int>> grid = vector<vector<int>> (m, vector<int> (n, 0));

for(int i = 0;i < guards.size();i++) {
grid[guards[i][0]][guards[i][1]] = 'G';
}

for(int i = 0;i < walls.size();i++) {
grid[walls[i][0]][walls[i][1]] = 'W';
}

for(int i = 0;i < grid.size();i++) {
bool f = false;
for(int j = 0;j < grid[0].size();j++) {
if('G' == grid[i][j]) {
f = true;
} else if('W' == grid[i][j]) {
f = false;
} else {
if(f) {
grid[i][j] = 1;
}
}
}

f = false;
for(int j = grid[0].size() - 1;j >= 0;j--) {
if('G' == grid[i][j]) {
f = true;
} else if('W' == grid[i][j]) {
f = false;
} else {
if(f) {
grid[i][j] = 1;
}
}
}
}

for(int i = 0;i < grid[0].size();i++) {
bool f = false;
for(int j = 0;j < grid.size();j++) {
if('G' == grid[j][i]) {
f = true;
} else if('W' == grid[j][i]) {
f = false;
} else {
if(f) {
grid[j][i] = 1;
}
}
}

f = false;
for(int j = grid.size() - 1;j >= 0;j--) {
if('G' == grid[j][i]) {
f = true;
} else if('W' == grid[j][i]) {
f = false;
} else {
if(f) {
grid[j][i] = 1;
}
}
}
}

int ans = 0;
for(int i = 0;i < grid.size();i++) {
for(int j = 0;j < grid[0].size();j++) {
if(0 == grid[i][j]) {
ans++;
}
}
}

return ans;
}
};

LeetCode : 1424. Diagonal Traverse II

// TODO : 效能太差,耗用的記憶體太多class Solution {
public:
vector<int> findDiagonalOrder(vector<vector<int>>& nums) {
vector<int> ans;
vector<vector<int>> tmp = vector<vector<int>>(200005);

int base = 0;
for(int i = 0;i < nums.size();i++) {
for(int j = 0;j < nums[i].size();j++) {
tmp[base + j].push_back(nums[i][j]);
}
base++;
}

for(int i = 0;i < tmp.size();i++) {
for(int j = tmp[i].size() - 1;j >= 0;j--) {
ans.push_back(tmp[i][j]);
}
}

return ans;
}
};

LeetCode : 2087. Minimum Cost Homecoming of a Robot in a Grid

class Solution {
public:
int minCost(vector<int>& startPos, vector<int>& homePos, vector<int>& rowCosts, vector<int>& colCosts) {
int ans = 0;

int stx = startPos[0]; // startPos : x
int sty = startPos[1];
if(stx > homePos[0]) {
while(stx != homePos[0]) {
stx--;
ans += rowCosts[stx];
}
} else {
while(stx != homePos[0]) {
stx++;
ans += rowCosts[stx];
}
}

if(sty > homePos[1]) {
while(sty != homePos[1]) {
sty--;
ans += colCosts[sty];
}
} else {
while(sty != homePos[1]) {
sty++;
ans += colCosts[sty];
}
}

return ans;
}
};

LeetCode : 2201. Count Artifacts That Can Be Extracted

// TODO : 學習下 hash table 的解法
class Solution {
public:
int digArtifacts(int n, vector<vector<int>>& artifacts, vector<vector<int>>& dig) {
int ans = 0;
vector<vector<int>> grid = vector<vector<int>>(n, vector<int>(n, -1));
// 某個 artifact 所佔面積
vector<int> alla = vector<int>(artifacts.size(), 0);

// 因為 artifacts 間不會 overlap,所以
// 這邊最多也就是 1000000 , 應該是不會 TLE
for(int i = 0;i < artifacts.size();i++) {
for(int j = artifacts[i][0];j <= artifacts[i][2];j++) {
for(int q = artifacts[i][1];q <= artifacts[i][3];q++) {
grid[j][q] = i;
alla[i]++;
}
}
}

for(int i = 0;i < dig.size();i++) {
if(-1 != grid[dig[i][0]][dig[i][1]]) {
alla[grid[dig[i][0]][dig[i][1]]]--;
}
}

for(int i = 0;i < alla.size();i++) {
if(0 == alla[i]) {
ans++;
}
}

return ans;
}

};

LeetCode : 2274. Maximum Consecutive Floors Without Special Floors

class Solution {
public:
int maxConsecutive(int bottom, int top, vector<int>& special) {
int bot = bottom - 1;
int t = top + 1;

vector<int> sp = special;
special.push_back(bot);
special.push_back(t);

sort(special.begin(), special.end());

int maxVal = INT_MIN;
for(int i = 1;i < special.size();i++) {
int tmp = special[i] - special[i - 1] - 1;
maxVal = max(maxVal, tmp);
}

return maxVal;
}
};

LeetCode : 1855. Maximum Distance Between a Pair of Values

class Solution {
public:
int maxDistance(vector<int>& nums1, vector<int>& nums2) {

int i = 0;
int j = 0;
int maxVal = 0;
while(i < nums1.size() && j < nums2.size()) {
if(i > j) {
j++;
} else if(nums1[i] <= nums2[j]) {
maxVal = max(maxVal, j - i);
j++;
} else {
i++;
}
}
return maxVal;
}
};

LeetCode : 2105. Watering Plants II

class Solution {
public:

bool water(int plant, int capacity, int *capa) {
bool result = false;
if(*capa >= plant) {
result = false;
} else {
*capa = capacity;
result = true;
}

*capa -= plant;

return result;
}

int minimumRefill(vector<int>& plants, int capacityA, int capacityB) {
int ali = 0;
int bob = plants.size() - 1;
int ans = 0;

int capaA = capacityA;
int capaB = capacityB;

while(ali <= bob) {
if(ali != bob) {
if(water(plants[ali], capacityA, &capaA)) {
ans++;
}

if(water(plants[bob], capacityB, &capaB)) {
ans++;
}

ali++;
bob--;
} else {
if(capaA >= capaB) {
if(water(plants[ali], capacityA, &capaA)) {
ans++;
}
} else {
if(water(plants[bob], capacityB, &capaB)) {
ans++;
}
}
break;
}
}

return ans;
}
};

LeetCode : 1438. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit

// TODO : 試試 Monotonic Queue 的解法
class Solution {
public:
int longestSubarray(vector<int>& nums, int limit) {

map<int, int> m;
int left = 0;
int right = 0;
m[nums[0]] = true;

int maxVal = 1;

while(left <= right && right < nums.size()) {
auto it_small = m.begin();
auto it_big = m.rbegin();

int small = it_small->first;
int big = it_big->first;

if(big - small <= limit) {
maxVal = max(maxVal, right - left + 1);

right++;
if(right < nums.size()) {
m[nums[right]]++;
}
} else {
m[nums[left]]--;
if(0 == m[nums[left]]) {
m.erase(nums[left]);
}
left++;
}

}

return maxVal;
}
};

LeetCode : 2012. Sum of Beauty in the Array

// TODO : 效能太差class Solution {
public:
int sumOfBeauties(vector<int>& nums) {

vector<pair<int, int>> l2r = vector<pair<int, int>> (nums.size());
vector<pair<int, int>> r2l = vector<pair<int, int>> (nums.size());

int maxVal = INT_MIN;
for(int i = 0;i < nums.size();i++) {
if(nums[i] > maxVal) {
l2r[i] = {nums[i], i};
maxVal = nums[i];
}
}

int minVal = INT_MAX;
for(int i = nums.size() - 1;i >= 0;i--) {
if(nums[i] < minVal) {
r2l[i] = {nums[i], i};
minVal = nums[i];
}
}

int ans = 0;
for(int i = 1;i < nums.size() - 1;i++) {
if(nums[i] == nums[i - 1] ||
nums[i] == nums[i + 1]) {

} else if (nums[i] == l2r[i].first &&
i == l2r[i].second &&
nums[i] == r2l[i].first &&
i == r2l[i].second) {
ans += 2;
} else if(nums[i] > nums[i - 1] &&
nums[i] < nums[i + 1]) {
ans += 1;
}
}

return ans;
}
};

LeetCode : 2261. K Divisible Elements Subarrays

// TODO : 效能真的太差了
// TODO : 我猜 trie 有機會 ?
class Solution {
public:
int countDistinct(vector<int>& nums, int k, int p) {

map<vector<int>, bool> m;
vector<bool> rec = vector<bool>(nums.size(), false);
for(int i = 0;i < nums.size();i++) {
if(0 == nums[i] % p) {
rec[i] = true;
}
}

for(int i = 0;i < nums.size();i++) {
vector<int> tmp;
int nown = 0;
for(int j = i;j < nums.size();j++) {
if(rec[j]) {
nown++;
}
if(nown > k) {
break;
}
tmp.push_back(nums[j]);
m[tmp] = true;
}
}

return m.size();
}
};

LeetCode : 2365. Task Scheduler II

#define LL long long
class Solution {
public:
long long taskSchedulerII(vector<int>& tasks, int space) {

unordered_map<LL, LL> um;
LL nowd = 0;


for(int i = 0;i < tasks.size();i++) {
if(um.find(tasks[i]) == um.end()) {
nowd++;
um[tasks[i]] = nowd;
} else {
LL lastday = um[tasks[i]];
if(lastday + space >= nowd) {
nowd = lastday + space + 1;
} else {
nowd++;
}
um[tasks[i]] = nowd;
}
}

return nowd;
}
};

LeetCode : 848. Shifting Letters

#define LL long long
class Solution {
public:
string shiftingLetters(string s, vector<int>& shifts) {
string ans;
vector<LL> tmp = vector<LL>(s.size(), 0);

vector<LL> shifSum = vector<LL>(s.size(), 0);
shifSum[shifSum.size() - 1] = shifts.back();
for(int i = shifts.size() - 2;i >= 0;i--) {
shifSum[i] = shifSum[i + 1] + shifts[i];
}

for(int i = 0;i < s.size();i++) {
tmp[i] = s[i] - 'a';
tmp[i] += shifSum[i];
tmp[i] %= 26;
ans.push_back('a' + tmp[i]);
}

return ans;
}
};

LeetCode : 822. Card Flipping Game

// 題目有點難懂
// 簡單來說,某個 int 是 good,代表他會在 facing down 出現,但不會在 facing up 出現。
// 因為數字總數只有 2000,所以遍尋每一個數字即可
class Solution {
public:
int flipgame(vector<int>& fronts, vector<int>& backs) {

vector<bool> rec = vector<bool>(2001, false);

for(int i = 0;i < fronts.size();i++) {
rec[fronts[i]] = true;
rec[backs[i]] = true;
}

for(int i = 0;i < fronts.size();i++) {
if(fronts[i] == backs[i]) {
rec[fronts[i]] = false;
}
}

for(int i = 1;i <= 2000;i++) {
if(rec[i]) {
return i;
}
}

return 0;
}
};

LeetCode : 2391. Minimum Amount of Time to Collect Garbage

class Solution {
public:
int garbageCollection(vector<string>& garbage, vector<int>& travel) {

int mfinal = -1;
int pfinal = -1;
int gfinal = -1;
for(int i = 0;i < garbage.size();i++) {
for(int j = 0;j < garbage[i].size();j++) {
switch(garbage[i][j]) {
case 'M':
mfinal = i;
break;
case 'P':
pfinal = i;

break;
case 'G':
gfinal = i;
break;
}
}
}

int ans = 0;
for(int i = 0;i < garbage.size();i++) {
if(i < garbage.size() - 1) {
if(i + 1 <= mfinal) {
ans += travel[i];
}
if(i + 1 <= pfinal) {
ans += travel[i];
}
if(i + 1 <= gfinal) {
ans += travel[i];
}
}

ans += garbage[i].size();
}

return ans;
}
};

LeetCode : 1868. Product of Two Run-Length Encoded Arrays

class Solution {
public:
vector<vector<int>> findRLEArray(vector<vector<int>>& encoded1, vector<vector<int>>& encoded2) {
vector<vector<int>> ans;
vector<vector<int>> tmp;
int i1 = 0;
int i2 = 0;

while(i1 < encoded1.size() && i2 < encoded2.size()) {
int tmpv = encoded1[i1][0] * encoded2[i2][0];
if(encoded1[i1][1] == encoded2[i2][1]) {
tmp.push_back({tmpv, encoded2[i2][1]});
i1++;
i2++;
} else if(encoded1[i1][1] > encoded2[i2][1]) {
tmp.push_back({tmpv, encoded2[i2][1]});
encoded1[i1][1] -= encoded2[i2][1];
i2++;
} else if(encoded1[i1][1] < encoded2[i2][1]) {
tmp.push_back({tmpv, encoded1[i1][1]});
encoded2[i2][1] -= encoded1[i1][1];
i1++;
}
}

while(i1 < encoded1.size()) {
tmp.push_back(encoded1[i1]);
i1++;
}

while(i2 < encoded2.size()) {
tmp.push_back(encoded2[i2]);
i2++;
}

int nowv = tmp[0][0];
int nown = tmp[0][1];
for(int i = 1;i < tmp.size();i++) {
if(tmp[i][0] == nowv) {
nown += tmp[i][1];
} else {
ans.push_back({nowv, nown});
nowv = tmp[i][0];
nown = tmp[i][1];
}
}
ans.push_back({nowv, nown});

return ans;
}
};

LeetCode : 1060. Missing Element in Sorted Array

// medium
// TODO : Follow Up
class Solution {
public:
int missingElement(vector<int>& nums, int k) {
int tmpk = k;
nums.push_back(200000000);
for(int i = 0;i < nums.size() - 1;i++) {
if(nums[i + 1] > nums[i] + 1) {
int diff = nums[i + 1] - nums[i];
if(diff - 1 < tmpk) {
tmpk -= (diff - 1);
} else {
return nums[i] + tmpk;
}
}
}
return 0;
}
};

LeetCode : 2061. Number of Spaces Cleaning Robot Cleaned

// TODO : 效能太差了
// 猜是 medium
// 每到一個格子時,除了記錄到過這個格子,也要記錄到這個格子時面向的方向
// 假如到某個格子且這個方向也相同,就表示可以停下來了
class Solution {
public:

int X[4] = {0, 1, 0, -1};
int Y[4] = {1, 0, -1, 0};

int numberOfCleanRooms(vector<vector<int>>& room) {
vector<vector<vector<bool>>> visited = vector<vector<vector<bool>>> (room.size(), vector<vector<bool>>(room[0].size(), vector<bool>(4, false)));

vector<vector<bool>> v2 = vector<vector<bool>>(room.size(), vector<bool>(room[0].size(), false));

int x = 0;
int y = 0;
// direction
int d = 0;
int ans = 0;

while(1) {
visited[x][y][d] = true;

if(!v2[x][y]) {
v2[x][y] = true;
ans++;
}

bool flag = false;
for(int i = 0;i < 4;i++) {
int newd = (d + i) % 4;
int newx = x + X[newd];
int newy = y + Y[newd];

if (newx >= 0 && newx < room.size() &&
newy >= 0 && newy < room[0].size() &&
1 != room[newx][newy]) {
flag = true;

x = newx;
y = newy;
d = newd;

break;
}
}

if(visited[x][y][d]) {
break;
}

if (!flag) {
break;
}
}

return ans;
}
};

LeetCode : 2405. Optimal Partition of String

// TODO : 應該還是太慢了
class Solution {
public:
int partitionString(string s) {
int ans = 0;
vector<int> rec = vector<int>(26, 0);
int left = 0;
rec[s[0] - 'a']++;
for(int i = 1;i < s.size();i++) {
rec[s[i] - 'a']++;
bool f = false;
for(int j = 0;j < 26;j++) {
if(rec[j] > 1) {
f = true;
break;
}
}
if(f) {
ans++;
while(left < i) {
rec[s[left] - 'a']--;
left++;
}
}
}

return ans + 1;
}
};

LeetCode : 2270. Number of Ways to Split Array

#define LL long long
class Solution {
public:
int waysToSplitArray(vector<int>& nums) {
LL sum = 0;
for(int i = 0;i < nums.size();i++) {
sum += nums[i];
}
LL nows = 0;
int ans = 0;
for(int i = 0;i < nums.size() - 1;i++) {
nows += nums[i];
if(nows >= (sum - nows)) {
ans++;
}
}

return ans;
}
};

LeetCode : 2090. K Radius Subarray Averages

#define LL long long
class Solution {
public:
vector<int> getAverages(vector<int>& nums, int k) {
vector<int> ans = vector<int>(nums.size(), 0);

for(int i = 0;i < k && i < nums.size();i++) {
ans[i] = -1;
ans[ans.size() - i - 1] = -1;
}

if(k * 2 + 1 > nums.size()) {
return ans;
}

int end = k * 2;
int len = k * 2 + 1;
LL nows = 0;
queue<int> q;

for(int i = 0;i <= end;i++) {
nows += nums[i];
q.push(nums[i]);
}
ans[k] = nows / len;

for(int i = k + 1;i < nums.size() - k;i++) {
nows -= nums[i - k - 1];
nows += nums[i + k];
q.push(nums[i + k]);

ans[i] = nows / len;
}

return ans;
}
};

LeetCode : 218. The Skyline Problem

// TODO : 效能太差,程式碼太醜bool myCompare_r2l(vector<int> &a, vector<int> &b) {
if(a[1] == b[1]) {
return a[2] < b[2];
}
return a[1] < b[1];
}
bool myCompare_l2r(vector<int> &a, vector<int> &b) {
if(a[0] == b[0]) {
return a[2] < b[2];
}
return a[0] < b[0];
}

class Solution {
public:
vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {
vector<vector<int>> ans;

if(buildings.size() == 0) {
return ans;
}

unordered_map<int, int> r2b;
unordered_map<int, int> l2b;
unordered_map<int, int> b2h;

for(int i = 0;i < buildings.size();i++) {
// 這裡沒考慮到 index
r2b[buildings[i][1]] = i;
l2b[buildings[i][0]] = i;
b2h[i] = buildings[i][2];
}

vector<vector<int>> building_sorted;
vector<vector<int>> building_rsorted;// = buildings;

for(int i = 0;i < buildings.size();i++) {
building_sorted.push_back({buildings[i][0], buildings[i][1], buildings[i][2], i});
building_rsorted.push_back({buildings[i][0], buildings[i][1], buildings[i][2], i});
}
sort(building_sorted.begin(), building_sorted.end(), myCompare_l2r);
sort(building_rsorted.begin(), building_rsorted.end(), myCompare_r2l);

vector<vector<int>> events;

int lsortedI = 0; //left sorted index
int rsortedI = 0; //right sorted index

while(lsortedI < building_sorted.size() && rsortedI < building_rsorted.size()) {
if(building_sorted[lsortedI][0] < building_rsorted[rsortedI][1]) {
events.push_back({0, building_sorted[lsortedI][3], building_sorted[lsortedI][0]});
lsortedI++;
} else {
events.push_back({1, building_rsorted[rsortedI][3], building_rsorted[rsortedI][1]});
rsortedI++;
}
}

while(lsortedI != buildings.size()) {
events.push_back({0, building_sorted[lsortedI][3], building_sorted[lsortedI][0]});
lsortedI++;
}

while(rsortedI != building_rsorted.size()) {
events.push_back({1, building_rsorted[rsortedI][3], building_rsorted[rsortedI][1]});
rsortedI++;
}

// events {left or right, 建築的 index, 現在的 x 值}
// 反正我們已經照著 x 走了,應該不需要紀錄現在的 x 了吧? --> 要得 QQ , 解答需要

map<int, int> nowHs;
int lastHighest = -1;
int nowHigh = -1;
int lastx = -1;

for(int i = 0;i < events.size();i++) {

if(i == 0) {
} else {
if(events[i][2] != lastx) {
// one step
if(ans.size() == 0) {
ans.push_back({lastx, nowHigh});
} else {
if(ans.back()[1] != nowHigh) {
ans.push_back({lastx, nowHigh});
}
}
}
}

int height = b2h[events[i][1]];
if(events[i][0] == 0) {
nowHs[height]++;
} else {
nowHs[height]--;
if(nowHs[height] == 0) {
nowHs.erase(height);
}
}

if(i == 0) {
lastx = events[i][2];
if(nowHs.size() == 0) {
nowHigh = 0;
} else {
nowHigh = nowHs.rbegin()->first;
}
} else {
if(events[i][2] != lastx) {
// one step
lastx = events[i][2];
if(nowHs.size() == 0) {
nowHigh = 0;
} else {
nowHigh = nowHs.rbegin()->first;
}
} else {
if(nowHs.size() == 0) {
nowHigh = 0;
} else {
nowHigh = nowHs.rbegin()->first;
}
}
}

}

ans.push_back({events.back()[2], 0});

return ans;
}
};

LeetCode : 2424. Longest Uploaded Prefix

// TODO : 效能太差
class LUPrefix {
public:
vector<bool> v;
int i = 1;
LUPrefix(int n) {
v = vector<bool>(n + 1, false);
}

void upload(int video) {
v[video] = true;
}

int longest() {
while(v[i]) {
i++;
}
return i - 1;
}
};
/**
* Your LUPrefix object will be instantiated and called as such:
* LUPrefix* obj = new LUPrefix(n);
* obj->upload(video);
* int param_2 = obj->longest();
*/

LeetCode : 16. 3Sum Closest

class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
int ans = 0;
int offset = 1e9;

sort(nums.begin(), nums.end());

for(int i = 0;i < nums.size()-2;i++){
int left = i+1;
int right = nums.size()-1;

while(left < right){
int sum = nums[i] + nums[left] + nums[right];

if(sum == target){
return target;
} else if(sum < target){
if((target - sum) < offset){
ans = sum;
offset = target-sum;
}

left++;
} else {
if((sum - target) < offset){
ans = sum;
offset = sum - target;
}

right--;
}
}
}

return ans;

}
};

LeetCode : 334. Increasing Triplet Subsequence

// TODO : 效能太差,沒有做出 follow up
class Solution {
public:

// https://leetcode.com/problems/increasing-triplet-subsequence/discuss/78993/Clean-and-short-with-comments-C%2B%2B
// 簡單易懂,但我完完全全沒想過...好強

bool increasingTriplet(vector<int>& nums) {
map<int, int> r2l;
map<int, int> l2r;

for(int i = nums.size() - 1;i >= 0;i--) {
r2l[nums[i]]++;
}

for(int i = 0;i < nums.size();i++) {
r2l[nums[i]]--;
if(r2l[nums[i]] == 0) {
r2l.erase(nums[i]);
}

if(i != 0 &&
i != nums.size() - 1) {
auto left = l2r.begin()->first;
auto right = r2l.rbegin()->first;

if(left < nums[i] &&
right > nums[i]) {
return true;
}
}

l2r[nums[i]]++;
}

return false;
}
};

LeetCode : 1995. Count Special Quadruplets

// TODO : 效能太差
class Solution {
public:
int countQuadruplets(vector<int>& nums) {
unordered_map<int, bool> um;
int ans = 0;
for(int i = 0;i < nums.size();i++) {
um[nums[i]] = true;
}

for(int i = 0;i < nums.size();i++) {
for(int j = i + 1;j < nums.size();j++) {
for(int q = j + 1;q < nums.size();q++) {
for(int p = q + 1;p < nums.size();p++) {
if (nums[i] + nums[j] + nums[q] == nums[p]) {
ans++;
}
}
}
}
}

return ans;
}
};

LeetCode : 2462. Total Cost to Hire K Workers

// TODO : 效能太差
#define LL long long
class Solution {
public:
long long totalCost(vector<int>& costs, int k, int candidates) {
map<LL, int> left;
map<LL, int> right;
LL ans = 0;

if (costs.size() >= 2 * candidates) {
int lefti = candidates;
int righti = costs.size() - 1 - candidates;
for(int i = 0;i < candidates;i++) {
left[costs[i]]++;
right[costs[costs.size() - 1 - i]]++;
}

for(int i = 0;i < k;i++) {
int minvl = INT_MAX;
int minvr = INT_MAX;

if(left.size() > 0) {
minvl = left.begin()->first;
}
if(right.size() > 0) {
minvr = right.begin()->first;
}

if(minvl <= minvr) {
left[minvl]--;
if(left[minvl] == 0) {
left.erase(minvl);
}

ans += minvl;
if (lefti <= righti) {
left[costs[lefti]]++;
lefti++;
}
} else {
right[minvr]--;
if(right[minvr] == 0) {
right.erase(minvr);
}

ans += minvr;
if (lefti <= righti) {
right[costs[righti]]++;
righti--;
}
}
}

} else {
for(int i = 0;i < costs.size();i++) {
left[costs[i]]++;
}

for(int i = 0;i < k;i++) {
int minv = left.begin()->first;
left[minv]--;
if(left[minv] == 0) {
left.erase(minv);
}
ans += minv;
}
}

return ans;
}
};

LeetCode : 2078. Two Furthest Houses With Different Colors

// TODO : 效能太差,有辦法再降複雜度嗎?
class Solution {
public:
int maxDistance(vector<int>& colors) {
int maxVal = INT_MIN;
for(int i = 0;i < colors.size();i++) {
for(int j = i + 1;j < colors.size();j++) {
if(colors[i] != colors[j]) {
maxVal = max(maxVal, abs(i - j));
}
}
}
return maxVal;
}
};

LeetCode : 2210. Count Hills and Valleys in an Array

// TODO : 應該有效能更好的做法
class Solution {
public:
int countHillValley(vector<int>& nums) {
int ans = 0;
vector<int> newnums;
int last = -1;
for(int i = 0;i < nums.size();i++) {
if (nums[i] != last) {
newnums.push_back(nums[i]);
last = nums[i];
}
}
for(int i = 1;i < newnums.size() - 1;i++) {
if((newnums[i - 1] > newnums[i] &&
newnums[i + 1] > newnums[i]) ||
(newnums[i - 1] < newnums[i] &&
newnums[i + 1] < newnums[i])) {
ans++;
}
}
return ans;
}
};

LeetCode : 2229. Check if an Array Is Consecutive

// TODO : 效能太差了
class Solution {
public:
bool isConsecutive(vector<int>& nums) {
unordered_map<int, bool> um;
int minVal = INT_MAX;
int maxVal = INT_MIN;
for(int i = 0;i < nums.size();i++) {
minVal = min(minVal, nums[i]);
maxVal = max(maxVal, nums[i]);
um[nums[i]] = true;
}
if((maxVal - minVal + 1) != nums.size()) {
return false;
}
for(int i = minVal;i <= maxVal;i++) {
if(!um[i]) {
return false;
}
}
return true;
}
};

LeetCode : 2482. Difference Between Ones and Zeros in Row and Column

class Solution {
public:
vector<vector<int>> onesMinusZeros(vector<vector<int>>& grid) {
vector<int> onesRow = vector<int>(grid.size());
vector<int> onesCol = vector<int>(grid[0].size());
vector<int> zerosRow = vector<int>(grid.size());
vector<int> zerosCol = vector<int>(grid[0].size());
vector<vector<int>> ans = vector<vector<int>>(grid.size(), vector<int>(grid[0].size(), 0));

for(int i = 0;i < grid.size();i++) {
int oneNum = 0;
int zeroNum = 0;
for(int j = 0;j < grid[0].size();j++) {
if(grid[i][j] == 1) {
oneNum++;
} else {
zeroNum++;
}
}
onesRow[i] = oneNum;
zerosRow[i] = zeroNum;
}
for(int i = 0;i < grid[0].size();i++) {
int oneNum = 0;
int zeroNum = 0;
for(int j = 0;j < grid.size();j++) {
if(grid[j][i] == 1) {
oneNum++;
} else {
zeroNum++;
}
}
onesCol[i] = oneNum;
zerosCol[i] = zeroNum;
}

for(int i = 0;i < grid.size();i++) {
for(int j = 0;j < grid[0].size();j++) {
ans[i][j] = onesRow[i] + onesCol[j] - zerosRow[i] - zerosCol[j];
}
}

return ans;
}
};

LeetCode : 2350. Shortest Impossible Sequence of Rolls

// TODO : 找找看有沒有辦法不要每輪都重新 vector<bool>(k + 1, false) ??
/*
一:
暴力解,從長度為 1 的陣列開始試每一種排列組合
每生成一種組合,就使用字串搜尋去找

二:
二分搜加上暴力解:
長度使用二分搜,使用該長度去生成每一種排列組合

p.s.
sequence 也包含重複
--> 很關鍵的性質 XDD,幸好有想到這個點,是解題的關鍵
e.g.
k = 2
--> 1, 1
1, 2
2, 1
2, 2

三:
概念:
dp[x] , 當 index 為 x 時,k 的值
現在從最簡單的開始思考,從 k = 1 開始湊
每當我們集齊 k 種數字,此時該 index 就會變成 dp[x] = 1
從這個 index 開始,再集齊 k 種數字,該 index 就能變成 dp[x] = 2
-->
從對右邊開始往左掃
每集齊 k 種數字,就將計數器 + 1 ,並重新開始蒐集 k 種數字
*/

class Solution {
public:
int shortestSequence(vector<int>& rolls, int k) {
vector<bool> rec = vector<bool>(k + 1, false);
int ans = 0;
int nowk = k;
for(int i = rolls.size() - 1;i >= 0;i--) {
if(!rec[rolls[i]]) {
nowk--;
rec[rolls[i]] = true;

if(nowk == 0) {
ans++;
nowk = k;
rec = vector<bool>(k + 1, false);
}
}
}
return ans + 1;
}
};

LeetCode : 2502. Design Memory Allocator

// TODO : 效能太差了
class Allocator {
private:
vector<int> m;
public:
Allocator(int n) {
m = vector<int>(n, 0);
}

int allocate(int size, int mID) {
vector<int> tmp = vector<int>(m.size(), 0);
for(int i = m.size() - 1;i >= 0;i--) {
if(m[i] == 0) {
if(i == m.size() - 1) {
tmp[i] = 1;
} else {
tmp[i] = tmp[i + 1] + 1;
}
} else {
tmp[i] = 0;
}
}

/*
printf("tmp : ");
for(int i = 0;i < tmp.size();i++) {
printf("%d ", tmp[i]);
}
printf("\n");*/
int starti = -1;
for(int i = 0;i < tmp.size();i++) {
if(tmp[i] >= size) {
starti = i;
break;
}
}
if(starti == -1) {
return -1;
}
for(int i = 0;i < size;i++) {
m[starti + i] = mID;
}
return starti;
}

int free(int mID) {
int ans = 0;
for(int i = 0;i < m.size();i++) {
if(m[i] == mID) {
ans++;
m[i] = 0;
}
}
return ans;
}
};

/**
* Your Allocator object will be instantiated and called as such:
* Allocator* obj = new Allocator(n);
* int param_1 = obj->allocate(size,mID);
* int param_2 = obj->free(mID);
*/

LeetCode : 2511. Maximum Enemy Forts That Can Be Captured

// TODO : 效能應該可以再優化
class Solution {
public:
int captureForts(vector<int>& forts) {
int maxval = 0;
for (int i = 0; i < forts.size(); i++) {
if (forts[i] != 1) {
continue;
}
int tmpi = i;
int tmp = 0;
bool found = false;
tmpi--;
while(tmpi >= 0) {
if(forts[tmpi] == 0) {
tmp++;
} else if (forts[tmpi] == -1) {
found = true;
break;
} else {
break;
}
tmpi--;
}
if (found) {
maxval = max(maxval, tmp);
}

tmpi = i;
tmp = 0;
found = false;
tmpi++;

while(tmpi < forts.size()) {
if (forts[tmpi] == 0) {
tmp++;
} else if (forts[tmpi] == -1) {
found = true;
break;
} else {
break;
}
tmpi++;
}
if (found) {
maxval = max(maxval, tmp);
}
}

return maxval;
}
};

LeetCode : 2555. Maximize Win From Two Segments

// 想法 1. segment tree
// 想法 2. priority queue
// 想法 3. queue
// 想法 4. 建表與查表
// --> 先看每個 x 會拿到多少值
// --> 再查表看 x + k + 1 以後,最多能拿到多少值

// 注意到這題不是求 1 segment,而是求 2 segment。
// TODO : 用錯了,這邊應該是要用 queue 才對!
// TODO : 效能還有很大的改善空間
// NOTE : 有趣的一題! 花了很多時間 (也可能是我太廢 QQ)
class Solution {
public:
int maximizeWin(vector<int>& prizePositions, int k) {
if(prizePositions.size() == 0) {
return 0;
}

unordered_map<int, bool> re;
vector<int> dis;
for(int i = 0; i < prizePositions.size(); i++) {
if(re.find(prizePositions[i]) == re.end()) {
re[prizePositions[i]] = true;
dis.push_back(prizePositions[i]);
}
}

// 找出 dis[x] + k 的 index
// dis_jump[x] == -1,代表沒辦法往下跳了
vector<int> dis_jump = vector<int>(dis.size(), -1);
int left = 0;
for(int i = 0;i < dis.size();i++) {
if(dis[i] > dis[left] + k) {
dis_jump[left] = i;
left++;
}
}

// tbl_val[x] 代表當我們選擇 dis[x] 作為出發點時,可以拿到什麼值
vector<int> tbl_val = vector<int>(dis.size(), 0);
queue<int> q;
int righti = 0;

for(int i = 0;i < dis.size();i++) {
if (i > 0) {
while(!q.empty() && dis[i] > q.front()) {
q.pop();
}
}
while(righti < prizePositions.size() &&
prizePositions[righti] == dis[i]) {
q.push(prizePositions[righti]);
righti++;
}
while(righti < prizePositions.size() &&
prizePositions[righti] - q.front() <= k) {
q.push(prizePositions[righti]);
righti++;
}
tbl_val[i] = q.size();
}

// tbl_max[x] 代表 dis >= dis[x] 時,所能取得的最大值
vector<int> tbl_max = vector<int>(dis.size(), 0);
int tmp_max = INT_MIN;
for(int i = tbl_val.size() - 1;i >= 0;i--) {
tmp_max = max(tbl_val[i], tmp_max);
tbl_max[i] = tmp_max;
}

// 遍尋 tbl_val, tbl_max 這兩張表來求解
int ans = INT_MIN;
for(int i = 0;i < tbl_val.size();i++) {
int ans2 = 0;
if (dis_jump[i] != -1) {
ans2 = tbl_max[dis_jump[i]];
}
ans = max(ans, tbl_val[i] + ans2);
}

return ans;
}
};

--

--

吳建興
吳建興

Written by 吳建興

I want to be a good programmer.(´・ω・`)

No responses yet