LeetCode-32

第 388 场周赛

100233. 重新分装苹果

  • 贪心
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public:
int minimumBoxes(vector<int>& apple, vector<int>& capacity) {
int need = accumulate(apple.begin(), apple.end(), 0);
sort(capacity.begin(), capacity.end());
int ans = 0, total = 0;
for(int i = capacity.size() - 1; i >= 0; i--) {
if(total < need) {
total += capacity[i];
ans++;
} else {
break;
}
}
return ans;
}
};

100247. 幸福值最大化的选择方案

  • 贪心
阅读更多

LeetCode-多线程-1

1115. 交替打印 FooBar

信号量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class FooBar {
private int n;
private Semaphore fooSem, barSem;
public FooBar(int n) {
this.n = n;
fooSem = new Semaphore(1);
barSem = new Semaphore(0);
}

public void foo(Runnable printFoo) throws InterruptedException {

for (int i = 0; i < n; i++) {

// printFoo.run() outputs "foo". Do not change or remove this line.
fooSem.acquire();
printFoo.run();
barSem.release();
}
}

public void bar(Runnable printBar) throws InterruptedException {

for (int i = 0; i < n; i++) {

// printBar.run() outputs "bar". Do not change or remove this line.
barSem.acquire();
printBar.run();
fooSem.release();
}
}
}

条件变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class FooBar {
private int n;
Lock lock;
Condition condition;
boolean fooOrBar = true;
public FooBar(int n) {
this.n = n;
lock = new ReentrantLock();
condition = lock.newCondition();
}

public void foo(Runnable printFoo) throws InterruptedException {

for (int i = 0; i < n; i++) {

// printFoo.run() outputs "foo". Do not change or remove this line.
lock.lock();
while(!fooOrBar) {
condition.await();
}
printFoo.run();
fooOrBar = !fooOrBar;
condition.signalAll();
lock.unlock();
}
}

public void bar(Runnable printBar) throws InterruptedException {

for (int i = 0; i < n; i++) {

// printBar.run() outputs "bar". Do not change or remove this line.
lock.lock();
while(fooOrBar) {
condition.await();
}
printBar.run();
fooOrBar = !fooOrBar;
condition.signalAll();
lock.unlock();
}
}
}

1116. 打印零与奇偶数

阅读更多

LeetCode-数据库-2

584. 寻找用户推荐人

1
2
3
4
5
6
7
8
SELECT
name
FROM
Customer
WHERE
referee_id <> 2
OR
referee_id IS NULL

577. 员工奖金

1
2
3
4
5
6
7
8
9
10
11
SELECT
E.name,
B.bonus
FROM
Employee E
LEFT JOIN Bonus B
ON E.empId = B.empId
WHERE
B.bonus < 1000
OR
B.bonus IS NULL

570. 至少有5名直接下属的经理

1
2
3
4
5
6
7
8
9
10
SELECT 
E1.name
FROM
Employee E1
LEFT JOIN Employee E2
ON E1.id = E2.managerId
GROUP BY
E1.id
HAVING
COUNT(E1.id) >= 5
阅读更多

LeetCode-33

232. 用栈实现队列

  • 两个栈倒腾一下可以得到队列
  • 一个栈用来入队
  • 一个栈用来出队,如果出队栈空,将另一个栈全倒腾过来,如果不空,就出栈一个元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class MyQueue {
stack<int> inStk, outStk;
public:
MyQueue() {

}

void push(int x) {
inStk.push(x);
}

int pop() {
if(outStk.empty()) {
while(!inStk.empty()) {
outStk.push(inStk.top());
inStk.pop();
}
}
int top = outStk.top();
outStk.pop();
return top;
}

int peek() {
if(outStk.empty()) {
while(!inStk.empty()) {
outStk.push(inStk.top());
inStk.pop();
}
}
int top = outStk.top();
return top;
}

bool empty() {
return inStk.empty() && outStk.empty();
}
};

1976. 到达目的地的方案数

dijkstra

  • 数据范围很大,枚举所有路径是不现实的
  • 由于我们只要求两点之间的最短路,所以用dijkstra就好
  • 应该是dp吧,每次选取最小路径的点更新邻接节点
    • 若使其路径变小了,则到达该节点最短路径数等于根节点到达当前节点的最短路径数
    • 若路径长度等于该节点,则到达该节点最短路径数在原来数量上加上根节点到达当前节点的最短路径数
阅读更多

LeetCode-32

1185. 一周中的第几天

  • Tomohiko Sakamoto算法
  • 虽然是简单题也有很多知识点呢
  • 解释
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public:
string dayOfTheWeek(int day, int month, int year) {
// array with leading number of days values
static int t[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };

// if month is less than 3 reduce year by 1
if (month < 3)
year -= 1;

return vector<string>{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}
[((year + year / 4 - year / 100 + year / 400 + t[month - 1] + day) % 7)];
}
};

2583. 二叉树中的第 K 大层和

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
public:
long long kthLargestLevelSum(TreeNode* root, int k) {
if(!root) return -1;
priority_queue<long long> level_sum_q;
queue<TreeNode *> q;
q.push(root);
while(!q.empty()) {
int q_size = q.size();
long long level_sum = 0;
while(q_size--) {
TreeNode *node = q.front();
q.pop();
level_sum += node->val;
if(node->left) q.push(node->left);
if(node->right) q.push(node->right);
}
level_sum_q.push(level_sum);
}
while(--k && !level_sum_q.empty()) {
level_sum_q.pop();
}
return !level_sum_q.empty() ? level_sum_q.top() : -1;
}
};
  • 用ranges获取第k大的数
阅读更多

LeetCode-31

1276. 不浪费原料的汉堡制作方案

  • 解方程,判断是非负整数解就行
  • 用位运算,能快一点
1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public:
vector<int> numOfBurgers(int tomatoSlices, int cheeseSlices) {
int jumbo = 0, small = 0;
// jumbo + small == cheeseSlices;
// 4*jumbo + 2*small == tomatoSlices;
small = ((cheeseSlices << 2) - tomatoSlices);
jumbo = (tomatoSlices - (cheeseSlices << 1));
if(jumbo >= 0 && small >= 0 && (small & 1) == 0 && (jumbo & 1) == 0)
return {jumbo >> 1, small >> 1};
return {};
}
};

1185. 一周中的第几天

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
public:
string dayOfTheWeek(int day, int month, int year) {
int week = 0;
for(int i = 1971; i < year; i++) {
week = (week + 31 * 7 + 30 * 4 + 28) % 7;
if((i % 100 != 0 && i % 4 == 0) || i % 400 == 0) {
week = (week + 1) % 7;
}
}
for(int i = 1; i < month; i++) {
if(i == 2) {
week = (week + 28) % 7;
if((year % 100 != 0 && year % 4 == 0) || year % 400 == 0) {
week = (week + 1) % 7;
}
} else if(i == 1 || i == 3 || i == 5 || i == 7 || i == 8 || i == 10 || i == 12) {
week = (week + 31) % 7;
} else {
week = (week + 30) % 7;
}
}
week = (week + day + 4) % 7;
return vector<string>{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}[week];
}
};
阅读更多

LeetCode-单调栈

739. 每日温度

  • 简单,通过单调栈,弹出栈中小于当前元素的元素,可以找到弹出元素的第一个大于其的位置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
stack<int> monoStk;
int len = temperatures.size();
vector<int> res(len);
for(int i = 0; i < len; i++) {
while(!monoStk.empty() && temperatures[monoStk.top()] < temperatures[i]) {
int top = monoStk.top();
res[top] = i - top;
monoStk.pop();
}
monoStk.push(i);
}
return res;
}
};

42. 接雨水

AC1

思路

阅读更多

LeetCode-30

162. 寻找峰值

1
2
3
4
5
6
7
8
9
class Solution {
public:
int findPeakElement(vector<int>& nums) {
int index = 0;
int n = nums.size();
while(index < n-1 && nums[index] < nums[index+1]) index++;
return index;
}
};

1901. 寻找峰值 II

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
public:
vector<int> findPeakGrid(vector<vector<int>>& mat) {
int x = 0, y = 0;
int m = mat.size(), n = mat[0].size();
bool findPoint = true;
while(findPoint) {
findPoint = false;
if(x + 1 < m && mat[x+1][y] > mat[x][y]) {
findPoint = true;
x++;
} else if(x - 1 >= 0 && mat[x-1][y] > mat[x][y]) {
findPoint = true;
x--;
} else if(y + 1 < n && mat[x][y+1] > mat[x][y]) {
findPoint = true;
y++;
} else if(y - 1 >= 0 && mat[x][y-1] > mat[x][y]) {
findPoint = true;
y--;
}

}
return {x, y};
}
};

贪心,从某一点开始,如果上下左右存在比当前点大的数,移动过去,直到无法移动

746. 使用最小花费爬楼梯

阅读更多

LeetCode-29

2661. 找出叠涂元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public:
int firstCompleteIndex(vector<int>& arr, vector<vector<int>>& mat) {
int m = mat.size(), n = mat[0].size();
vector<int> cnt_row(m, 0), cnt_col(n, 0);
vector<int> index(m*n+1);
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
index[mat[i][j]] = i*n+j;
}
}
int len = arr.size();
for(int i = 0; i < len; i++) {
int x = index[arr[i]]/n, y = index[arr[i]]%n;
cnt_row[x]++;
cnt_col[y]++;
if(cnt_row[x] == n || cnt_col[y] == m) return i;
}
return -1;
}
};

1657. 确定两个字符串是否接近

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
public:
inline bool logicXor(bool a, bool b) {
return (a && !b) || (b && !a);
}
bool closeStrings(string word1, string word2) {
vector<int> word1_cnt(26, 0), word2_cnt(26, 0);
for(char c : word1) {
word1_cnt[c - 'a']++;
}
for(char c : word2) {
word2_cnt[c - 'a']++;
}
for(int i = 0; i < 26; i++) {
if(logicXor(word1_cnt[i] == 0, word2_cnt[i] == 0)) return false;
}
sort(word1_cnt.begin(), word1_cnt.end());
sort(word2_cnt.begin(), word2_cnt.end());
for(int i = 0; i < 26; i++) {
if(word1_cnt[i] != word2_cnt[i]) return false;
}
return true;
}
};

2336. 无限集中的最小数字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
class SmallestInfiniteSet {
vector<pair<unsigned, unsigned>> s;
public:
SmallestInfiniteSet() {
s.emplace_back(1, -1);
}

int popSmallest() {
int smallest = s[0].first++;
if(s[0].first == s[0].second) {
s.erase(s.begin());
}
return smallest;
}

void addBack(int num) {
// cout << "add\n";
int n = s.size();
int i = 0;
while(i < n && s[i].second <= num) i++;
if(i >= n) {
s.emplace_back(num, num + 1);
return;
}
if(s[i].first <= num) {
return;
} else {
if(s[i].first-1 == num) {
s[i].first--;
// 检查前面的,拼接
if(i-1 >= 0 && s[i-1].second == s[i].first) {
s[i-1].second = s[i].second;
s.erase(s.begin() + i);
}
} else {
if(i - 1 >= 0 && s[i-1].second == num) {
s[i-1].second++;
} else {
s.insert(s.begin() + i, make_pair(num, num+1));
}
}
}
}
};

/**
* Your SmallestInfiniteSet object will be instantiated and called as such:
* SmallestInfiniteSet* obj = new SmallestInfiniteSet();
* int param_1 = obj->popSmallest();
* obj->addBack(num);
*/
阅读更多