跳至主要内容

856. Score of Parentheses

· 閱讀時間約 1 分鐘
/*
* @lc app=leetcode id=856 lang=cpp
*
* [856] Score of Parentheses
*
* https://leetcode.com/problems/score-of-parentheses/description/
*
* algorithms
* Medium (63.90%)
* Likes: 5526
* Dislikes: 229
* Total Accepted: 205.7K
* Total Submissions: 322.7K
* Testcase Example: '"()"'
*
* Given a balanced parentheses string s, return the score of the string.
*
* The score of a balanced parentheses string is based on the following
* rule:
*
*
* "()" has score 1.
* AB has score A + B, where A and B are balanced parentheses strings.
* (A) has score 2 * A, where A is a balanced parentheses string.
*
*
*
* Example 1:
*
*
* Input: s = "()"
* Output: 1
*
*
* Example 2:
*
*
* Input: s = "(())"
* Output: 2
*
*
* Example 3:
*
*
* Input: s = "()()"
* Output: 2
*
*
*
* Constraints:
*
*
* 2 <= s.length <= 50
* s consists of only '(' and ')'.
* s is a balanced parentheses string.
*
*
*/

// @lc code=start
class Solution {
public:
int scoreOfParentheses(string s) {
int res = 0;
stack<int> stk;
for (auto c : s) {
if(c == '(') {
stk.push(res);
res = 0;
} else {
if (res == 0) {
res = 1 + stk.top();
} else {
res = res * 2 + stk.top();
}
stk.pop();
}
}
return res;
}
};
// @lc code=end

846. Hand of Straights

· 閱讀時間約 2 分鐘

Alice has some number of cards and she wants to rearrange the cards into groups so that each group is of size groupSize, and consists of groupSize consecutive cards.

Given an integer array hand where hand[i] is the value written on the ith card and an integer groupSize, return true if she can rearrange the cards, or false otherwise.

Example 1:

Input: hand = [1,2,3,6,2,3,4,7,8], groupSize = 3 Output: true Explanation: Alice's hand can be rearranged as [1,2,3],[2,3,4],[6,7,8]

Example 2:

Input: hand = [1,2,3,4,5], groupSize = 4 Output: false Explanation: Alice's hand can not be rearranged into groups of 4.

Constraints:

  • 1 <= hand.length <= 104
  • 0 <= hand[i] <= 109
  • 1 <= groupSize <= hand.length
class Solution {
public:
bool isNStraightHand(vector<int>& hand, int groupSize) {
int n = hand.size();
if(n % groupSize) return false;

// 使用 TreeMap 計算每個數字的頻率
// TreeMap 裡面的 key 會從小到大排列
map<int, int> freq;
for(auto h : hand) ++freq[h];

while(!freq.empty()) {
// TreeMap 的第一個數字,也就是陣列裡最小的數字
int first = freq.begin()->first;

// 從 first 當作起始點,遞增到 < first + groupSize
// 也就是遞增到每個 group 的最大值
for(int i = first; i < first + groupSize; ++i){

// 如果 i 不存在 freq 裡的話,代表這個數字已經被其他 group 用完了
if(!freq.count(i)) {
return false;
}

// 如果 i 存在在 freq 裡的話,頻率減一
--freq[i];

// 頻率扣到為 0 的話,刪除這個 key
if(freq[i] == 0) {
freq.erase(i);
}
}
}
return true;
}
};
  • T: $O(n \cdot \log n)$
  • S: $O(n)$

844. Backspace String Compare

· 閱讀時間約 2 分鐘

Given two strings s and t, return true if they are equal when both are typed into empty text editors. '#' means a backspace character.

Note that after backspacing an empty text, the text will continue empty.

Example 1:

Input: s = "ab#c", t = "ad#c" Output: true Explanation: Both s and t become "ac".

Example 2:

Input: s = "ab##", t = "c#d#" Output: true Explanation: Both s and t become "".

Example 3:

Input: s = "a#c", t = "b" Output: false Explanation: s becomes "c" while t becomes "b".

Constraints:

  • 1 <= s.length, t.length <= 200
  • s and t only contain lowercase letters and '#' characters.

Follow up: Can you solve it in O(n) time and O(1) space?

  • 計數器 for # 號,count 多少,就要退幾格
  • 遇到 ``#` 號,指針略過繼續走
  • 指針從最右到左,其中一個字串沒刪完就繼續刪
class Solution {
public:
bool backspaceCompare(string s, string t) {
int i = s.size() - 1;
int j = t.size() - 1;

int s_backspace_count = 0;
int t_backspace_count = 0;

// 只要其中一個字串沒有掃完,就繼續掃
while(i >= 0 || j >= 0) {
while(i >= 0) {
if(s[i] == '#') {
--i;
// 要扣掉的數量 + 1
++s_backspace_count;
} else if(s_backspace_count > 0) {
--i;
--s_backspace_count;
} else break;
}
while(j >= 0) {
if(t[j] == '#') {
--j;
++t_backspace_count;
} else if(t_backspace_count > 0) {
--j;
--t_backspace_count;
} else break;
}
// 如果發現 char 不一樣,直接 return false
if (i >= 0 && j >= 0 && s[i] != t[j])
return false;

// 如果都被扣光光了,檢查 i 跟 j 是否相等
// 這行可以讓程式 early return
if(i < 0 || j < 0) return i == j;
--i; --j;
}
return i == j;
}
};
  • T: $O(M + N)$
  • S: $O(1)$

840. Magic Squares In Grid

· 閱讀時間約 2 分鐘
  • Brute-force
class Solution {
public:
int numMagicSquaresInside(vector<vector<int>>& grid)
{
int m = grid.size(), n = grid[0].size();
int res = 0;
for (int i = 0; i < m - 2; i++)
{
for (int j = 0; j < n - 2; j++)
{
if (isMagicSqures(grid, i, j)) res++;
}
}
return res;
}

bool isMagicSqures(vector<vector<int>>& grid, int r, int c)
{
vector<bool> seen(10);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
int num = grid[r + i][c + j];
if (num < 1 || num > 9) return false;
if (seen[num]) return false;
seen[num] = true;
}
}

int postiveDiag = grid[r + 2][c] + grid[r + 1][c + 1] + grid[r][c + 2];
int negativeDiag = grid[r][c] + grid[r + 1][c + 1] + grid[r + 2][c + 2];

if (postiveDiag != negativeDiag) return false;

int r1 = grid[r][c] + grid[r + 1][c] + grid[r + 2][c];
int r2 = grid[r][c + 1] + grid[r + 1][c + 1] + grid[r + 2][c + 1];
int r3 = grid[r][c + 2] + grid[r + 1][c + 2] + grid[r + 2][c + 2];

if (r1 != postiveDiag || r2 != postiveDiag || r3 != postiveDiag) return false;

int c1 = grid[r][c] + grid[r][c + 1] + grid[r][c + 2];
int c2 = grid[r + 1][c] + grid[r + 1][c + 1] + grid[r + 1][c + 2];
int c3 = grid[r + 2][c] + grid[r + 2][c + 1] + grid[r + 2][c + 2];

if (c1 != postiveDiag || c2 != postiveDiag || c3 != postiveDiag) return false;

return true;
}
};
  • T: $O(m \cdot n)$
  • S: $O(1)$

826. Most Profit Assigning Work

· 閱讀時間約 1 分鐘
  • 工人派遣工作,一人只能被指派一個工作,但是一個工作可以被做很多遍。
  • 初始化 {difficulty, profit} pair jobs
  • 排序 worker, jobs
  • 雙指針法搭配 Greedy 找最大獲利。
class Solution {
public:
int maxProfitAssignment(vector<int>& difficulty, vector<int>& profit, vector<int>& worker)
{
int n = difficulty.size();

// {difficulty, profit} pair
vector<pair<int, int>> jobs;

for (int i = 0; i < n; ++i)
{
jobs.push_back({difficulty[i], profit[i]});
}

sort(jobs.begin(), jobs.end());
sort(worker.begin(), worker.end());

// 雙指針法
int res = 0;
int i = 0;
int cur = 0;
for (auto w : worker)
{
while (i < n && w >= jobs[i].first)
{
cur = max(cur, jobs[i++].second);
}
res += cur;
}
return res;
}
};
  • T: $O(n \cdot \log n + m \cdot \log m)$
  • S: $O(n)$

783. Minimum Distance Between BST Nodes

· 閱讀時間約 1 分鐘

Hint

/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
vector<int> v;
public:
int minDiffInBST(TreeNode* root)
{
dfs(root);
sort(v.begin(), v.end());
int minDiff = INT_MAX;
for (int i = 1; i < v.size(); i++)
{
minDiff = min(minDiff, v[i] - v[i - 1]);
}
return minDiff;
}
void dfs(TreeNode* root)
{
if(!root) return;
dfs(root->left);
v.push_back(root->val);
dfs(root->right);
}
};
  • T: $O()$
  • S: $O()$

746. Min Cost Climbing Stairs

· 閱讀時間約 2 分鐘
/*
* @lc app=leetcode id=746 lang=cpp
*
* [746] Min Cost Climbing Stairs
*
* https://leetcode.com/problems/min-cost-climbing-stairs/description/
*
* algorithms
* Easy (66.19%)
* Likes: 11495
* Dislikes: 1777
* Total Accepted: 1.3M
* Total Submissions: 1.9M
* Testcase Example: '[10,15,20]'
*
* You are given an integer array cost where cost[i] is the cost of i^th step
* on a staircase. Once you pay the cost, you can either climb one or two
* steps.
*
* You can either start from the step with index 0, or the step with index 1.
*
* Return the minimum cost to reach the top of the floor.
*
*
* Example 1:
*
*
* Input: cost = [10,15,20]
* Output: 15
* Explanation: You will start at index 1.
* - Pay 15 and climb two steps to reach the top.
* The total cost is 15.
*
*
* Example 2:
*
*
* Input: cost = [1,100,1,1,1,100,1,1,100,1]
* Output: 6
* Explanation: You will start at index 0.
* - Pay 1 and climb two steps to reach index 2.
* - Pay 1 and climb two steps to reach index 4.
* - Pay 1 and climb two steps to reach index 6.
* - Pay 1 and climb one step to reach index 7.
* - Pay 1 and climb two steps to reach index 9.
* - Pay 1 and climb one step to reach the top.
* The total cost is 6.
*
*
*
* Constraints:
*
*
* 2 <= cost.length <= 1000
* 0 <= cost[i] <= 999
*
*
*/

// @lc code=start
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost)
{
vector<int> dp(cost.size() + 1);
for (int i = 2; i < cost.size() + 1; ++i)
{
int one = dp[i - 1] + cost[i - 1];
int two = dp[i - 2] + cost[i - 2];
dp[i] = min(one, two);
}
return dp.back();
}
};
// @lc code=end
  • T: $O(N)$
  • S: $O(N)$

DP Improved

class Solution {
public:
int minCostClimbingStairs(vector<int>& cost)
{
int one = 0, two = 0;
for (int i = 2; i <= cost.size(); i++)
{
int temp = one;
one = min(one + cost[i - 1], two + cost[i - 2]);
two = temp;
}
return one;
}
};
  • T: $O(N)$
  • S: $O(1)$

739. Daily Temperatures

· 閱讀時間約 1 分鐘

Given an array of integers temperatures represents the daily temperatures, return an array answer such that answer[i] is the number of days you have to wait after the ith day to get a warmer temperature. If there is no future day for which this is possible, keep answer[i] == 0 instead.

Example 1:

Input: temperatures = [73,74,75,71,69,72,76,73] Output: [1,1,4,2,1,1,0,0]

Example 2:

Input: temperatures = [30,40,50,60] Output: [1,1,1,0]

Example 3:

Input: temperatures = [30,60,90] Output: [1,1,0]

Constraints:

  • 1 <= temperatures.length <= 105
  • 30 <= temperatures[i] <= 100
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
int n = temperatures.size();
stack<int> st;
vector<int> res(n);
for(int i = 0; i < n; i++) {
// 當遇到溫度是比較高的時候
while(!st.empty() && temperatures[i] > temperatures[st.top()]) {
// 拿到前一天的 index
int previousDay = st.top(); st.pop();

// 計算 index 差,也就是差幾天
int dayDiff = i - previousDay;

// 將結果存到 res
res[previousDay] = dayDiff;
}
// 將 index 存到 stack
st.push(i);
}
return res;
}
};
  • T: $O(N)$
  • S: $O(N)$

733. Flood Fill

· 閱讀時間約 1 分鐘
  • DFS
class Solution {
public:
vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int color)
{
int originalColor = image[sr][sc];
if (color == originalColor) return image;
dfs(image, sr, sc, color, originalColor);
return image;
}

void dfs(vector<vector<int>>& image, int i, int j, int color, int originalColor)
{
if (i < 0 || j < 0 || i >= image.size() || j >= image[0].size() || image[i][j] == color || image[i][j] != originalColor)
return;

image[i][j] = color;

vector<vector<int>> directions = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
for (const auto& dir : directions)
{
dfs(image, i + dir[0], j + dir[1], color, originalColor);
}
}
};
  • T: $O(m \cdot n)$。
  • S: $O(1)$。