第一次参加周赛就单双周一起报了。刷的题还不多,因此每场只记录2-3道自己掌握的(比赛时提交通过或完了通不过,事后看一眼就明白怎么回事的)。Cuz my current goal is to get completely control of questions which are easy or medium-hard to solve(The label "hard" marked by LeetCode could be medium-hard or "medium" could be hard for me, it depends"). 保持我的习惯,还是用英文书写annotations.
题目来自于leetcode
https://leetcode-cn.com/contest/weekly-contest-161
🏆第 12 场双周赛
第一题
1244. Design A Leaderboard
Design a Leaderboard class, which has 3 functions:
addScore(playerId, score): Update the leaderboard by addingscoreto the given player's score. If there is no player with such id in the leaderboard, add him to the leaderboard with the givenscore.top(K): Return the score sum of the topKplayers.reset(playerId): Reset the score of the player with the given id to 0. It is guaranteed that the player was added to the leaderboard before calling this function.
Initially, the leaderboard is empty.
Example 1:
Input:
["Leaderboard","addScore","addScore","addScore","addScore","addScore","top","reset","reset","addScore","top"]
[[],[1,73],[2,56],[3,39],[4,51],[5,4],[1],[1],[2],[2,51],[3]]
Output:
[null,null,null,null,null,null,73,null,null,null,141]
Explanation:
Leaderboard leaderboard = new Leaderboard ();
leaderboard.addScore(1,73); // leaderboard = [[1,73]];
leaderboard.addScore(2,56); // leaderboard = [[1,73],[2,56]];
leaderboard.addScore(3,39); // leaderboard = [[1,73],[2,56],[3,39]];
leaderboard.addScore(4,51); // leaderboard = [[1,73],[2,56],[3,39],[4,51]];
leaderboard.addScore(5,4); // leaderboard = [[1,73],[2,56],[3,39],[4,51],[5,4]];
leaderboard.top(1); // returns 73;
leaderboard.reset(1); // leaderboard = [[2,56],[3,39],[4,51],[5,4]];
leaderboard.reset(2); // leaderboard = [[3,39],[4,51],[5,4]];
leaderboard.addScore(2,51); // leaderboard = [[2,51],[3,39],[4,51],[5,4]];
leaderboard.top(3); // returns 141 = 51 + 51 + 39;
Constraints:
1 <= playerId, K <= 10000- It's guaranteed that
Kis less than or equal to the current number of players. 1 <= score <= 100- There will be at most
1000function calls.
code:
class Leaderboard {
public:
Leaderboard() {
}
void addScore(int playerId, int score) {
map<int,int>::iterator find_player = player_score.find(playerId);
if(find_player==player_score.end())
{
player_score.insert(map<int,int>::value_type(playerId, score));
}else{
player_score[playerId] += score;
}
}
int top(int K) {
vector<int> scores;
for(auto it = player_score.begin(); it!=player_score.end();it++)
{
scores.push_back(it->second);
}
sort(scores.begin(), scores.end());
int res = 0;
for(int i = 0; i<K; i++)
{
res += scores[scores.size()-i-1];
}
return res;
}
void reset(int playerId) {
player_score[playerId] = 0;
}
private:
map<int,int> player_score;
};
comment:
This is really not a medium level of question, it's "so easy". only the function "int top(int K)" need to do some "algorithm". And we can use #include <algorithm>'s "sort()" function to deal with it. However, sort() can only sort a "vector" type, we gotta push the whole map into a vector before sorting.
第二题
1243. Array Transformation
Given an initial array arr, every day you produce a new array using the array of the previous day.
On the i-th day, you do the following operations on the array of day i-1 to produce the array of day i:
- If an element is smaller than both its left neighbor and its right neighbor, then this element is incremented.
- If an element is bigger than both its left neighbor and its right neighbor, then this element is decremented.
- The first and last elements never change.
After some days, the array does not change. Return that final array.
Example 1:
Input: arr = [6,2,3,4]
Output: [6,3,3,4]
Explanation:
On the first day, the array is changed from [6,2,3,4] to [6,3,3,4].
No more operations can be done to this array.
Example 2:
Input: arr = [1,6,3,4,3,5]
Output: [1,4,4,4,4,5]
Explanation:
On the first day, the array is changed from [1,6,3,4,3,5] to [1,5,4,3,4,5].
On the second day, the array is changed from [1,5,4,3,4,5] to [1,4,4,4,4,5].
No more operations can be done to this array.
Constraints:
1 <= arr.length <= 1001 <= arr[i] <= 100
code:
class Solution {
public:
vector<int> transformArray(vector<int>& arr) {
if(arr.size()==1||arr.size()==2)
{
return arr;
}
vector<int> last_arr = arr;
vector<int> next_arr = arr;
bool is_complete = false;
bool changed = true;
while(changed){
changed = false;
for(int i = 1; i < arr.size()-1; i++)
{
if(next_arr[i]<last_arr[i-1]&&next_arr[i]<last_arr[i+1])
{
next_arr[i]++;
changed = true;
}else if(next_arr[i]>last_arr[i-1]&&next_arr[i]>last_arr[i+1])
{
next_arr[i]--;
changed = true;
}
}
last_arr = next_arr;
}
return last_arr;
}
};
comment:
It's easy. The tricky one is... look at the second example. When the array is [1,6,3,4,3,5], it transformed to [1,5,4,4,3,5] when i equals to 2. And when i equals to 3, should arr[3] ==4 reduce by 1 or not? It should reduce by 1, because we gotta compare with the array from the beginning of this loop [1,6,3,4,3,5] instead of [1,5,4,4,3,5] it transforms to. That's the reason I declare a variable "last_arr" represents the array from the beginning of a loop, and "next_arr" for the transformed array in a loop.
第三题:
1245. Tree Diameter
Given an undirected tree, return its diameter: the number of edges in a longest path in that tree.
The tree is given as an array of edges where edges[i] = [u, v] is a bidirectional edge between nodes u and v. Each node has labels in the set {0, 1, ..., edges.length}.
Example 1:

Input: edges = [[0,1],[0,2]]
Output: 2
Explanation:
A longest path of the tree is the path 1 - 0 - 2.
Example 2:

Input: edges = [[0,1],[1,2],[2,3],[1,4],[4,5]]
Output: 4
Explanation:
A longest path of the tree is the path 3 - 2 - 1 - 4 - 5.
Constraints:
0 <= edges.length < 10^4edges[i][0] != edges[i][1]0 <= edges[i][j] <= edges.length- The given edges form an undirected tree.
code:
class Solution {
public:
pair<int,int> bfs(vector<vector<int>> &edges_match_up, int start)
{
vector<int> path(edges_match_up.size(), -1);//if -1, unvisited
queue<int> Q;
Q.push(start);
path[start] = 0;//path be initialized with 0, it will be increased when diameter is growing
pair<int,int> ret;//ret.first is the point, ret.second is the length from point to start
while(!Q.empty())//in this loop, Q is empty means we visited all nodes
{
int x = Q.front();//let's visit this current Q front for this loop
Q.pop();//different from stack, queue is FIFO(but stack is FILO)
ret.first = x;
ret.second = path[x];
for(auto &it:edges_match_up[x])
{
if(path[it]==-1)
{
path[it] = path[x] + 1;//path[x] is current distance from start, plus one to grow it
Q.push(it);//push it into the queue to visit later
}
}
}
return ret;
}
int treeDiameter(vector<vector<int>>& edges) {
vector<vector<int>> edges_match_up(edges.size()+1, vector<int>());
for(auto &it:edges)
{
edges_match_up[it[0]].push_back(it[1]);
edges_match_up[it[1]].push_back(it[0]);
}
pair<int,int> p;
p = bfs(edges_match_up, 0);
p = bfs(edges_match_up, p.first);//cuz this invoke of bfs() is to calculate the end point,
//but the start point may not be an end point,
//the length was just a distance from start point to end point.
//Hence we have to invoke bfs for the second time,
//for calculating the distance, from end point to end point
return p.second;
}
};
comment:
This question is about a new algorithm for me. It's Breadth-First-Search(BFS). I got this from youtube and LeetCode discussion board then implemented here. Depth-First-Search(DFS) can do this still but the Time-Complexity could be worse. I think my annotations are clear enuf.
bfs to solve this:
code:
class Solution {
public:
void dfs(int current_node, int dis)
{
if(ans<dis)
{
ans = dis;
now_node = current_node;
}
visited[current_node] = 1;
for(int i = 0; i <e[current_node].size(); i++)
{
int v = e[current_node][i];
if(!visited[v])
{
dfs(v, dis+1);
}
}
}
int treeDiameter(vector<vector<int>>& edges) {
for(int i = 0; i <edges.size(); i ++)
{
e[edges[i][0]].push_back(edges[i][1]);
e[edges[i][1]].push_back(edges[i][0]);
}
dfs(0,0);
memset(visited, 0, sizeof(visited));
ans = 0;
dfs(now_node, 0);
return ans;
}
private:
vector<int> e[10004];
int ans = 0 , now_node = 0;
int visited[10004] = {0};
};
comment:
Some needed to be made clear is the declaration of size for 10004(both visited[10004] and e[10004]) is to guarantee the program run test cases throught. By the by it passed LeetCode's all test cases with visited[10000], e[10000]. Hence this over-guaranteed, but no skin off my nose.
🏆 第 161 场力扣周赛(单周赛)
第一题:
1247. Minimum Swaps to Make Strings Equal
You are given two strings s1 and s2 of equal length consisting of letters "x" and "y" only. Your task is to make these two strings equal to each other. You can swap any two characters that belong to different strings, which means: swap s1[i] and s2[j].
Return the minimum number of swaps required to make s1 and s2 equal, or return -1 if it is impossible to do so.
Example 1:
Input: s1 = "xx", s2 = "yy"
Output: 1
Explanation:
Swap s1[0] and s2[1], s1 = "yx", s2 = "yx".
Example 2:
Input: s1 = "xy", s2 = "yx"
Output: 2
Explanation:
Swap s1[0] and s2[0], s1 = "yy", s2 = "xx".
Swap s1[0] and s2[1], s1 = "xy", s2 = "xy".
Note that you can't swap s1[0] and s1[1] to make s1 equal to "yx", cause we can only swap chars in different strings.
Example 3:
Input: s1 = "xx", s2 = "xy"
Output: -1
Example 4:
Input: s1 = "xxyyxyxyxx", s2 = "xyyxyxxxyx"
Output: 4
Constraints:
1 <= s1.length, s2.length <= 1000s1, s2only contain'x'or'y'.
code:
class Solution {
public:
int minimumSwap(string s1, string s2) {
int x_up = 0; //L1.x&&L2.y
int y_up = 0; //L1.y&&L2.x
int res = 0;
for (int i = 0; i < s1.length(); i++)
{
if(s1[i] == s2[i])
{
continue;
}
else if(s1[i]=='x'&&s2[i]=='y')
{
x_up++;
}
else if(s1[i]=='y'&&s2[i]=='x')
{
y_up++;
}
}
if (x_up%2 + y_up%2 == 1)
{
return -1;
}
res = x_up/2 + y_up/2;
if(x_up%2 == 1)
{
res +=2;
}
return res;
}
};
comment:
I really got wrecked by myself for this question(during the competition). I found the rule to solve it but I did declare a string variable to do "exchange" xs and ys. However, "the rule" all of this question but "exchanging" is unnecessary, that's tricky, making program ways sooooooooooo sloooooow. Hence I couldn't pass Leet's devil test cases.

In a fact, the rule is simple as above. We exchange the upper x and lower y when we have 2 x-y pairs, in the meantime we exchange the upper y and lower x when we have 2 y-x pairs, each cost 1 step. The remain thing is we do 2 step to exchange 1 x-y pair and 1 y-x pair.
Only if we finish 2-pairs-exchanging①, and remain either 1 x-y pair or 1 y-x pair. We return -1. Hence if(x_up%2+ y_up%2 == 1) return -1;
① 2 x-y pairs or 2 y-x pairs.
第三题:
1249. Minimum Remove to Make Valid Parentheses
Given a string s of '(' , ')' and lowercase English characters.
Your task is to remove the minimum number of parentheses ( '(' or ')', in any positions ) so that the resulting parentheses string is valid and return any valid string.
Formally, a parentheses string is valid if and only if:
- It is the empty string, contains only lowercase characters, or
- It can be written as
AB(Aconcatenated withB), whereAandBare valid strings, or - It can be written as
(A), whereAis a valid string.
Example 1:
Input: s = "lee(t(c)o)de)"
Output: "lee(t(c)o)de"
Explanation: "lee(t(co)de)" , "lee(t(c)ode)" would also be accepted.
Example 2:
Input: s = "a)b(c)d"
Output: "ab(c)d"
Example 3:
Input: s = "))(("
Output: ""
Explanation: An empty string is also valid.
Example 4:
Input: s = "(a(b(c)d)"
Output: "a(b(c)d)"
Constraints:
1 <= s.length <= 10^5s[i]is one of'(',')'and lowercase English letters.
code:
class Solution {
public:
string minRemoveToMakeValid(string s) {
stack<int> the_stack;
vector<bool> paired_flag(s.length(), false);
for(int i = 0; i < s.length(); i++)
{
if(s[i]=='(')
{
the_stack.push(i);
}
else if(s[i]==')')
{
if(the_stack.empty())
{
continue;
}
paired_flag[the_stack.top()] = true;
paired_flag[i] = true;
the_stack.pop();
}else
{
continue;
}
}
string result = "";
for(int i = 0; i < s.length(); i++)
{
if((s[i]=='(')||(s[i]==')'))
{
if(paired_flag[i])
{
result += s[i];
}
}
else
{
result += s[i];
}
}
return result;
}
};
comment:
First of all we do a loop of s.length() to get brackets. We push the index of the string into a stack when loop encounter '('. We pop the index of the last left bracket index out of the stack when we meet ')'. And When we have ')' with our stack empty, we abandon this ')'. We also abandon the surplus '(' brackets after the loop. The "paired_flag" variable is to note the index of brackets we want(when it is true). We use cpp "stack", it has an attribute of "First In Last Of", which helps us easily solve the problem.
这篇博客记录了作者在LeetCode周赛中的体验,涉及了设计一个Leaderboard类,包括添加分数、获取前K名玩家总分和重置分数的功能。还介绍了如何解决数组变换问题,以及如何找到无向树的最大路径长度。每个问题都附带了解题思路和代码实现。

1221

被折叠的 条评论
为什么被折叠?



