We distribute some number of candies, to a row of n = num_people people in the following way:
We then give 1 candy to the first person, 2 candies to the second person, and so on until we give n candies to the last person.
Then, we go back to the start of the row, giving n + 1 candies to the first person, n + 2 candies to the second person, and so on until we give 2 * n candies to the last person.
This process repeats (with us giving one more candy each time, and moving to the start of the row after we reach the end) until we run out of candies. The last person will receive all of our remaining candies (not necessarily one more than the previous gift).
Return an array (of length num_people and sum candies) that represents the final distribution of candies.
Example 1:
1 2 3 4 5 6 7
Input: candies = 7, num_people = 4 Output: [1,2,3,1] Explanation: On the first turn, ans[0] += 1, and the array is [1,0,0,0]. On the second turn, ans[1] += 2, and the array is [1,2,0,0]. On the third turn, ans[2] += 3, and the array is [1,2,3,0]. On the fourth turn, ans[3] += 1 (because there is only one candy left), and the final array is [1,2,3,1].
Example 2:
1 2 3 4 5 6 7
Input: candies = 10, num_people = 3 Output: [5,2,3] Explanation: On the first turn, ans[0] += 1, and the array is [1,0,0]. On the second turn, ans[1] += 2, and the array is [1,2,0]. On the third turn, ans[2] += 3, and the array is [1,2,3]. On the fourth turn, ans[0] += 4, and the final array is [5,2,3].
只考虑每次分配的糖果数,分配的糖果数为1,2,3,4,5,…, 依次加1。再考虑到分配的轮数,可以利用 i % num_people 来求得第i次应该分配到第几个人。
classSolution { public: vector<int> distributeCandies(int candies, int num_people){ vector<int> res(num_people, 0); int temp = 1, i = 0; while(candies > 0) { res[i%num_people] += min(candies, i+1); candies -= min(candies, i+1); i ++; } return res; } };
Leetcode1104. Path In Zigzag Labelled Binary Tree
In an infinite binary tree where every node has two children, the nodes are labelled in row order.
In the odd numbered rows (ie., the first, third, fifth,…), the labelling is left to right, while in the even numbered rows (second, fourth, sixth,…), the labelling is right to left.
Given the label of a node in this tree, return the labels in the path from the root of the tree to the node with that label.
You are given an array books where books[i] = [thicknessi, heighti] indicates the thickness and height of the ith book. You are also given an integer shelfWidth.
We want to place these books in order onto bookcase shelves that have a total width shelfWidth.
We choose some of the books to place on this shelf such that the sum of their thickness is less than or equal to shelfWidth, then build another level of the shelf of the bookcase so that the total height of the bookcase has increased by the maximum height of the books we just put down. We repeat this process until there are no more books to place.
Note that at each step of the above process, the order of the books we place is the same order as the given sequence of books.
For example, if we have an ordered list of 5 books, we might place the first and second book onto the first shelf, the third book on the second shelf, and the fourth and fifth book on the last shelf. Return the minimum possible height that the total bookshelf can be after placing shelves in this manner.
Example 1:
1 2 3 4 5
Input: books = [[1,1],[2,3],[2,3],[1,1],[1,1],[1,1],[1,2]], shelf_width = 4 Output: 6 Explanation: The sum of the heights of the 3 shelves is 1 + 3 + 2 = 6. Notice that book number 2 does not have to be on the first shelf.
You are given an array of flight bookings bookings, where bookings[i] = [firsti, lasti, seatsi] represents a booking for flights firsti through lasti (inclusive) with seatsi seats reserved for each flight in the range.
Return an array answer of length n, where answer[i] is the total number of seats reserved for flight i.
Leetcode1111. Maximum Nesting Depth of Two Valid Parentheses Strings
A string is a valid parentheses string (denoted VPS) if and only if it consists of “(“ and “)” characters only, and:
It is the empty string, or
It can be written as AB (A concatenated with B), where A and B are VPS’s, or
It can be written as (A), where A is a VPS.
We can similarly define the nesting depth depth(S) of any VPS S as follows:
depth(“”) = 0
depth(A + B) = max(depth(A), depth(B)), where A and B are VPS’s
depth(“(“ + A + “)”) = 1 + depth(A), where A is a VPS.
For example, “”, “()()”, and “()(()())” are VPS’s (with nesting depths 0, 1, and 2), and “)(“ and “(()” are not VPS’s.
Given a VPS seq, split it into two disjoint subsequences A and B, such that A and B are VPS’s (and A.length + B.length = seq.length).
Now choose any such A and B such that max(depth(A), depth(B)) is the minimum possible value.
Return an answer array (of length seq.length) that encodes such a choice of A and B: answer[i] = 0 if seq[i] is part of A, else answer[i] = 1. Note that even though multiple answers may exist, you may return any of them.
public class Foo { public void first() { print("first"); } public void second() { print("second"); } public void third() { print("third"); } }
The same instance of Foo will be passed to three different threads. Thread A will call first(), thread B will call second(), and thread C will call third(). Design a mechanism and modify the program to ensure that second() is executed after first(), and third() is executed after second().
Example 1:
1 2 3
Input: [1,2,3] Output: "firstsecondthird" Explanation: There are three threads being fired asynchronously. The input [1,2,3] means thread A calls first(), thread B calls second(), and thread C calls third(). "firstsecondthird" is the correct output.
Example 2:
1 2 3
Input: [1,3,2] Output: "firstsecondthird" Explanation: The input [1,3,2] means thread A calls first(), thread B calls third(), and thread C calls second(). "firstsecondthird" is the correct output.
voidfirst(function<void()> printFirst){ // printFirst() outputs "first". Do not change or remove this line. printFirst(); m1.unlock(); }
voidsecond(function<void()> printSecond){ m1.lock(); // printSecond() outputs "second". Do not change or remove this line. printSecond(); m1.unlock(); m2.unlock(); }
voidthird(function<void()> printThird){ m2.lock(); // printThird() outputs "third". Do not change or remove this line. printThird(); m2.unlock(); } };
Leetcode1122. Relative Sort Array
Given two arrays arr1 and arr2, the elements of arr2 are distinct, and all elements in arr2 are also in arr1.
Sort the elements of arr1 such that the relative ordering of items in arr1 are the same as in arr2. Elements that don’t appear in arr2 should be placed at the end of arr1 in ascending order.
Leetcode1123. Lowest Common Ancestor of Deepest Leaves
Given a rooted binary tree, return the lowest common ancestor of its deepest leaves.
Recall that:
The node of a binary tree is a leaf if and only if it has no children
The depth of the root of the tree is 0, and if the depth of a node is d, the depth of each of its children is d+1.
The lowest common ancestor of a set S of nodes is the node A with the largest depth such that every node in S is in the subtree with root A.
Example 1:
1 2 3 4 5 6
Input: root = [1,2,3] Output: [1,2,3] Explanation: The deepest leaves are the nodes with values 2 and 3. The lowest common ancestor of these leaves is the node with value 1. The answer returned is a TreeNode object (not an array) with serialization "[1,2,3]".
Example 2:
1 2
Input: root = [1,2,3,4] Output: [4]
Example 3:
1 2
Input: root = [1,2,3,4,5] Output: [2,4,5]
Constraints:
The given tree will have between 1 and 1000 nodes.
Each node of the tree will have a distinct value between 1 and 1000.
classSolution { public: intlongestWPI(vector<int>& hours){ for(int i=0;i<hours.size();i++) hours[i]=hours[i]>8?1:-1; unordered_map<int, int> idx; int r = 0,inx=0; int last=0; int maxx=0; for(int i=0;i<hours.size();i++){ r += hours[i]; if(r>0){ maxx = i+1; } if (!idx.count(r)) idx[r] = i; if (idx.count(r - 1)) maxx = max(maxx, i - idx[r - 1]); } return maxx; } };
LeetCode] 1125. Smallest Sufficient Team
In a project, you have a list of required skills req_skills, and a list of people. The ith person people[i] contains a list of skills that the person has.
Consider a sufficient team: a set of people such that for every required skill in req_skills, there is at least one person in the team who has that skill. We can represent these teams by the index of each person.
For example, team = [0, 1, 3] represents the people with skills people[0], people[1], and people[3]. Return any sufficient team of the smallest possible size, represented by the index of each person. You may return the answer in any order.
It is guaranteed an answer exists.
Example 1:
1 2
Input: req_skills = ["java","nodejs","reactjs"], people = [["java"],["nodejs"],["nodejs","reactjs"]] Output: [0,2]
Example 2:
1 2
Input: req_skills = ["algorithms","math","java","reactjs","csharp","aws"], people = [["algorithms","math","java"],["algorithms","math","reactjs"],["java","csharp","aws"],["reactjs","csharp"],["csharp","math"],["aws","java"]] Output: [1,2]
Constraints:
1 <= req_skills.length <= 16
1 <= req_skills[i].length <= 16
req_skills[i] consists of lowercase English letters.
All the strings of req_skills are unique.
1 <= people.length <= 60
0 <= people[i].length <= 16
1 <= people[i][j].length <= 16
people[i][j] consists of lowercase English letters.
All the strings of people[i] are unique.
Every skill in people[i] is a skill in req_skills.
classSolution { public: vector<int> smallestSufficientTeam(vector<string>& req_skills, vector<vector<string>>& people){ int m = req_skills.size(), n = people.size(); int maxstate = 1 << m; // f[i][s] = 考虑前i个人的时候,状态为s所需的最小人数 vector<vector<int>> f(n+1, vector<int>(maxstate, 1e9)); // path[i][s] = 前i个人的时候,选人方案, vector<vector<longlong>> path(n+1, vector<longlong>(maxstate, 0)); f[0][0] = 0; for (int i = 1; i <= n; i ++) { int state = 0; for (constauto& str : people[i-1]) { int id = find(req_skills.begin(), req_skills.end(), str) - req_skills.begin(); state |= (1 << id); } for (int j = 0; j < maxstate; j ++) { if (f[i-1][j] < f[i][j]) { f[i][j] = f[i-1][j]; path[i][j] = path[i-1][j]; } int news = j | state; if (f[i-1][j] + 1 < f[i][news]) { f[i][news] = f[i-1][j] + 1; path[i][news] = path[i-1][j] | (1LL << i); } } } vector<int> ret; for (int i = 1; i <= n; i ++) if ((path[n][maxstate-1] >> i) & 1) ret.push_back(i-1); return ret; } };
Leetcode1128. Number of Equivalent Domino Pairs
Given a list of dominoes, dominoes[i] = [a, b] is equivalent to dominoes[j] = [c, d] if and only if either (a==c and b==d), or (a==d and b==c) - that is, one domino can be rotated to be equal to another domino.
Return the number of pairs (i, j) for which 0 <= i < j < dominoes.length, and dominoes[i] is equivalent to dominoes[j].
classSolution { public: intnumEquivDominoPairs(vector<vector<int>>& dominoes){ int temp; int ans = 0; map<int, int> mp;
for(int i = 0; i < dominoes.size(); i ++) { if(dominoes[i][0] > dominoes[i][1]) { temp = dominoes[i][0]; dominoes[i][0] = dominoes[i][1]; dominoes[i][1] = temp; } temp = dominoes[i][0]*10 + dominoes[i][1]; mp[temp] ++; } for(pair<int, int> i : mp) { int v = i.second; ans += (v*(v-1))/2; } return ans; } };
Leetcode1129. Shortest Path with Alternating Colors
Consider a directed graph, with nodes labelled 0, 1, …, n-1. In this graph, each edge is either red or blue, and there could be self-edges or parallel edges.
Each [i, j] in red_edges denotes a red directed edge from node i to node j. Similarly, each [i, j] in blue_edges denotes a blue directed edge from node i to node j.
Return an array answer of length n, where each answer[X] is the length of the shortest path from node 0 to node X such that the edge colors alternate along the path (or -1 if such a path doesn’t exist).
classSolution { public: vector<int> shortestAlternatingPaths(int n, vector<vector<int>>& red_edges, vector<vector<int>>& blue_edges){ vector<int> res(n); vector<vector<int>> dp(2, vector<int>(n)); vector<vector<unordered_set<int>>> graph(2, vector<unordered_set<int>>(n)); for (auto &edge : red_edges) { graph[0][edge[0]].insert(edge[1]); } for (auto &edge : blue_edges) { graph[1][edge[0]].insert(edge[1]); } for (int i = 1; i < n; ++i) { dp[0][i] = 2 * n; dp[1][i] = 2 * n; } queue<vector<int>> q; q.push({0, 0}); q.push({0, 1}); while (!q.empty()) { int cur = q.front()[0], color = q.front()[1]; q.pop(); for (int next : graph[1 - color][cur]) { if (dp[1 - color][next] == 2 * n) { dp[1 - color][next] = 1 + dp[color][cur]; q.push({next, 1 - color}); } } } for (int i = 0; i < n; ++i) { int val = min(dp[0][i], dp[1][i]); res[i] = val == 2 * n ? -1 : val; } return res; } };
Leetcode1130. Minimum Cost Tree From Leaf Values
Given an array arr of positive integers, consider all binary trees such that:
Each node has either 0 or 2 children;
The values of arr correspond to the values of each leaf in an in-order traversal of the tree. (Recall that a node is a leaf if and only if it has 0 children.)
The value of each non-leaf node is equal to the product of the largest leaf value in its left and right subtree respectively.
Among all possible binary trees considered, return the smallest possible sum of the values of each non-leaf node. It is guaranteed this sum fits into a 32-bit integer.
Example 1:
1 2 3 4 5 6 7 8 9 10
Input: arr = [6,2,4] Output: 32 Explanation: There are two possible trees. The first has non-leaf node sum 36, and the second has non-leaf node sum 32.
24 24 / \ /\ 12 4 6 8 / \ /\ 6 2 2 4
Constraints:
2 <= arr.length <= 40
1 <= arr[i] <= 15
It is guaranteed that the answer fits into a 32-bit signed integer (ie. it is less than 2^31).
classSolution { public: string alphabetBoardPath(string target){ string res; int curX = 0, curY = 0; for (char c : target) { int x = (c - 'a') / 5, y = (c - 'a') % 5; res += string(max(0, curX - x), 'U') + string(max(0, y - curY), 'R') + string(max(0, curY - y), 'L') + string(max(0, x - curX), 'D') + '!'; curX = x; curY = y; } return res; } };
Leetcode1139. Largest 1-Bordered Square
Given a 2D grid of 0s and 1s, return the number of elements in the largest square subgrid that has all 1s on its border, or 0 if such a subgrid doesn’t exist in the grid.
classSolution { public: intlargest1BorderedSquare(vector<vector<int>>& grid){ int m = grid.size(), n = grid[0].size(); vector<vector<int>> left(m, vector<int>(n)), top(m, vector<int>(n)); for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { if (grid[i][j] == 0) continue; left[i][j] = j == 0 ? 1 : left[i][j - 1] + 1; top[i][j] = i == 0 ? 1 : top[i - 1][j] + 1; } } for (int len = min(m, n); len > 0; --len) { for (int i = 0; i < m - len + 1; ++i) { for (int j = 0; j < n - len + 1; ++j) { if (top[i + len - 1][j] >= len && top[i + len - 1][j + len - 1] >= len && left[i][j + len - 1] >= len && left[i + len - 1][j + len - 1] >= len) return len * len; } } } return0; } };
上面的方法是根据边长进行遍历,若数组很大,而其中的1很少,这种遍历方法将不是很高效。我们从 grid 数组的右下角往左上角遍历,即从每个潜在的正方形的右下角开始遍历,根据右下顶点的位置取到的 top 和 left 值,分别是正方形的右边和下边的边长,取其中较小的那个为目标正方形的边长,然后现在就要确定是否存在相应的左边和上边,存在话的更新 mx,否则将目标边长减1,继续查找,直到目标边长小于 mx 了停止。继续这样的操作直至遍历完所有的右下顶点,这种遍历的方法要高效不少,参见代码如下:
classSolution { public: intlargest1BorderedSquare(vector<vector<int>>& grid){ int mx = 0, m = grid.size(), n = grid[0].size(); vector<vector<int>> left(m, vector<int>(n)), top(m, vector<int>(n)); for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { if (grid[i][j] == 0) continue; left[i][j] = j == 0 ? 1 : left[i][j - 1] + 1; top[i][j] = i == 0 ? 1 : top[i - 1][j] + 1; } } for (int i = m - 1; i >= 0; --i) { for (int j = n - 1; j >= 0; --j) { int small = min(left[i][j], top[i][j]); while (small > mx) { if (top[i][j - small + 1] >= small && left[i - small + 1][j] >= small) mx = small; --small; } } } return mx * mx; } };
Leetcode1140. Stone Game II
Alice and Bob continue their games with piles of stones. There are a number of piles arranged in a row, and each pile has a positive integer number of stones piles[i]. The objective of the game is to end with the most stones.
Alice and Bob take turns, with Alice starting first. Initially, M = 1.
On each player’s turn, that player can take all the stones in the first X remaining piles, where 1 <= X <= 2M. Then, we set M = max(M, X).
The game continues until all the stones have been taken.
Assuming Alice and Bob play optimally, return the maximum number of stones Alice can get.
Example 1:
1 2 3
Input: piles = [2,7,9,4,4] Output: 10 Explanation: If Alice takes one pile at the beginning, Bob takes two piles, then Alice takes 2 piles again. Alice can get 2 + 4 + 4 = 10 piles in total. If Alice takes two piles at the beginning, then Bob can take all three piles left. In this case, Alice get 2 + 7 = 9 piles in total. So we return 10 since it's larger.
Example 2:
1 2
Input: piles = [1,2,3,4,5,100] Output: 104
Constraints:
1 <= piles.length <= 100
1 <= piles[i] <= 104
这道题是石头游戏系列的第二道,跟之前那道 Stone Game 不同的是终于换回了 Alice 和 Bob!还有就是取石子的方法,不再是只能取首尾两端的石子堆,而是可以取 [1, 2M] 范围内的任意X堆,M是个变化的量,初始化为1,每次取完X堆后,更新为 M = max(M, X)。这种取石子的方法比之前的要复杂很多,由于X的值非常的多,而且其不同的选择还可能影响到M值,那么整体的情况就特别的多,暴力搜索基本上是行不通的。这种不同状态之间转移的问题用动态规划 Dynamic Programming 是比较合适的,首先来考虑 DP 数组的定义,题目要求的是 Alice 最多能拿到的石子个数,拿石子的方式是按顺序的,不能跳着拿,所以决定某个状态的是两个变量,一个是当前还剩多少石子堆,可以通过当前位置坐标i来表示,另一个是当前的m值,只有知道了当前的m值,那么选手才知道能拿的堆数的范围,所以 DP 就是个二维数组,其 dp[i][m] 表示的意义在上面已经解释了。接下来考虑状态转移方程,由于在某个状态时已经知道了m值,则当前选手能拿的堆数在范围 [1, 2m] 之间,为了更新这个 dp 值,所有x的情况都要遍历一遍,即在剩余堆数中拿x堆,但此时x堆必须小于等于剩余的堆数,即 i + x <= n,i为当前的位置。由于每个选手都是默认选最优解的,若能知道下一个选手该拿的最大石子个数,就能知道当前选手能拿的最大石子个数了,因为二者之和为当前剩余的石子个数。由于当前选手拿了x堆,则下个选手的位置是 i+x,且m更新为 max(m,x),所以其 dp 值为 dp[i + x][max(m, x)])。为了快速得知当前剩余的石子总数,需要建立累加和数组,注意这里是建立反向的累加和数组,其中 sums[i] 表示范围 [i, n-1] 之和。分析到这里就可以写出状态状态转移方程如下:
接下来就是一些初始化和边界定义的问题需要注意的了,dp 数组大小为 n+1 by n+1,因为选手是可能一次将n堆都拿了,比如 n=1 时,所以 dp[i][n] 是存在的,且需要用 sums[i] 来初始化。更新 dp 时需要用三个 for 循环,分别控制i,m,和 x,注意更新从后往前遍历i和m,因为我们要先更新小区间,再更新大区间。x的范围要设定为 x <= 2 * m && i + x <= n,前面也讲过原因了,最后的答案保存在 dp[0][1] 中返回即可,参见代码如下:
classSolution { public: intstoneGameII(vector<int>& piles){ int n = piles.size(); vector<int> sums = piles; vector<vector<int>> dp(n + 1, vector<int>(n + 1)); for (int i = n - 2; i >= 0; --i) { sums[i] += sums[i + 1]; } for (int i = 0; i < n; ++i) { dp[i][n] = sums[i]; } for (int i = n - 1; i >= 0; --i) { for (int m = n - 1; m >= 1; --m) { for (int x = 1; x <= 2 * m && i + x <= n; ++x) { dp[i][m] = max(dp[i][m], sums[i] - dp[i + x][max(m, x)]); } } } return dp[0][1]; } };
classSolution { public: intstoneGameII(vector<int>& piles){ int n = piles.size(); vector<int> sums = piles; vector<vector<int>> memo(n, vector<int>(n)); for (int i = n - 2; i >= 0; --i) { sums[i] += sums[i + 1]; } returnhelper(sums, 0, 1, memo); } inthelper(vector<int>& sums, int i, int m, vector<vector<int>>& memo){ if (i + 2 * m >= sums.size()) return sums[i]; if (memo[i][m] > 0) return memo[i][m]; int res = 0; for (int x = 1; x <= 2 * m; ++x) { int cur = sums[i] - sums[i + x]; res = max(res, cur + sums[i + x] - helper(sums, i + x, max(x, m), memo)); } return memo[i][m] = res; } };
Leetcode1143. Longest Common Subsequence
Given two strings text1 and text2, return the length of their longest common subsequence.
A subsequence of a string is a new string generated from the original string with some characters(can be none) deleted without changing the relative order of the remaining characters. (eg, “ace” is a subsequence of “abcde” while “aec” is not). A common subsequence of two strings is a subsequence that is common to both strings.
If there is no common subsequence, return 0.
Example 1:
1 2 3
Input: text1 = "abcde", text2 = "ace" Output: 3 Explanation: The longest common subsequence is "ace" and its length is 3.
Example 2:
1 2 3
Input: text1 = "abc", text2 = "abc" Output: 3 Explanation: The longest common subsequence is "abc" and its length is 3.
Example 3:
1 2 3
Input: text1 = "abc", text2 = "def" Output: 0 Explanation: There is no such common subsequence, so the result is 0.
Constraints:
1 <= text1.length <= 1000
1 <= text2.length <= 1000
The input strings consist of lowercase English characters only.
classSolution { public: intlongestCommonSubsequence(string word1, string word2){ int m = word1.length(), n = word2.length(); vector<vector<int>> dp(m+1, vector(n+1, 0)); for (int i = 1; i <= m; i ++) for (int j = 1; j <= n; j ++) if (word1[i-1] == word2[j-1]) dp[i][j] = dp[i-1][j-1] + 1; else dp[i][j] = max(dp[i-1][j], dp[i][j-1]); return dp[m][n]; } };
Leetcode1144. Decrease Elements To Make Array Zigzag
Given an array nums of integers, a move consists of choosing any element and decreasing it by 1.
An array A is a zigzag array if either:
Every even-indexed element is greater than adjacent elements, ie. A[0] > A[1] < A[2] > A[3] < A[4] > … OR, every odd-indexed element is greater than adjacent elements, ie. A[0] < A[1] > A[2] < A[3] > A[4] < … Return the minimum number of moves to transform the given array nums into a zigzag array.
Example 1:
1 2 3
Input: nums = [1,2,3] Output: 2 Explanation: We can decrease 2 to 0 or 3 to 1.
classSolution { public: intmovesToMakeZigzag(vector<int>& nums){ int n = nums.size(), res[2] = {0, 0}; for (int i = 0; i < n; ++i) { int left = i > 0 ? nums[i - 1] : 1001; int right = i < n - 1 ? nums[i + 1] : 1001; res[i % 2] += max(0, nums[i] - min(left, right) + 1); } returnmin(res[0], res[1]); } };
Leetcode1146. Snapshot Array
Implement a SnapshotArray that supports the following interface:
SnapshotArray(int length) initializes an array-like data structure with the given length. Initially, each element equals 0.
void set(index, val) sets the element at the given index to be equal to val.
int snap() takes a snapshot of the array and returns the snap_id: the total number of times we called snap() minus 1.
int get(index, snap_id) returns the value at the given index, at the time we took the snapshot with the given snap_id
Example 1:
1 2 3 4 5 6 7 8 9
Input: ["SnapshotArray","set","snap","set","get"] [[3],[0,5],[],[0,6],[0,0]] Output: [null,null,0,null,5] Explanation: SnapshotArray snapshotArr = new SnapshotArray(3); // set the length to be 3 snapshotArr.set(0,5); // Set array[0] = 5 snapshotArr.snap(); // Take a snapshot, return snap_id = 0 snapshotArr.set(0,6); snapshotArr.get(0,0); // Get the value of array[0] with snap_id = 0, return 5
Constraints:
1 <= length <= 50000
At most 50000 calls will be made to set, snap, and get.
0 <= index < length
0 <= snap_id < (the total number of times we call snap())
You are given a string text. You should split it to k substrings (subtext1, subtext2, …, subtextk) such that:
subtexti is a non-empty string.
The concatenation of all the substrings is equal to text (i.e., subtext1 + subtext2 + … + subtextk == text).
subtexti == subtextk - i + 1 for all valid values of i (i.e., 1 <= i <= k).
Return the largest possible value of k.
Example 1:
1 2 3
Input: text = "ghiabcdefhelloadamhelloabcdefghi" Output: 7 Explanation: We can split the string on "(ghi)(abcdef)(hello)(adam)(hello)(abcdef)(ghi)".
Example 2:
1 2 3
Input: text = "merchant" Output: 1 Explanation: We can split the string on "(merchant)".
Example 3:
1 2 3
Input: text = "antaprezatepzapreanta" Output: 11 Explanation: We can split the string on "(a)(nt)(a)(pre)(za)(tpe)(za)(pre)(a)(nt)(a)".
Example 4:
1 2 3
Input: text = "aaa" Output: 3 Explanation: We can split the string on "(a)(a)(a)".
Constraints:
1 <= text.length <= 1000
text consists only of lowercase English characters.
这道题是关于段式回文的,想必大家对回文串都不陌生,就是前后字符对应相同的字符串,比如 noon 和 bob。这里的段式回文相等的不一定是单一的字符,而是可以是字串,参见题目中的例子,现在给了一个字符串,问可以得到的段式回文串的最大长度是多少。由于段式回文的特点,你可以把整个字符串都当作一个子串,则可以得到一个长度为1的段式回文,所以答案至少是1,不会为0。而最好情况就是按字符分别相等,那就变成了一般的回文串,则长度就是原字符串的长度。比较的方法还是按照经典的验证回文串的方式,用双指针来做,一前一后。不同的是遇到不相等的字符不是立马退出,而是累加两个子串 left 和 right,每累加一个字符,都比较一下 left 和 right 是否相等,这样可以保证尽可能多的分出来相等的子串,一旦分出了相等的子串,则 left 和 right 重置为空串,再次从小到大比较,参见代码如下:
解法一:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
classSolution { public: intlongestDecomposition(string text){ int res = 0, n = text.size(); string left, right; for (int i = 0; i < n; ++i) { left += text[i], right = text[n - i - 1] + right; if (left == right) { ++res; left = right = ""; } } return res; } };
classSolution { public: boolis_equal(string text, int x, int y, int len){ for (int i = 0; i < len; i ++) if (text[x+i] != text[y+i]) returnfalse; returntrue; } intlongestDecomposition(string text){ int n = text.length(); for (int i = 1; i <= n/2; i ++) { if (is_equal(text, 0, n-i, i)) return2 + longestDecomposition(text.substr(i, n-i*2)); } return n > 0 ? 1 : 0; } };
Leetcode1154. Day of the Year
Given a string date representing a Gregorian calendar date formatted as YYYY-MM-DD, return the day number of the year.
Example 1:
1 2 3
Input: date = "2019-01-09" Output: 9 Explanation: Given date is the 9th day of the year in 2019.
Example 2:
1 2
Input: date = "2019-02-10" Output: 41
Example 3:
1 2
Input: date = "2003-03-01" Output: 60
Example 4:
1 2
Input: date = "2004-03-01" Output: 61
判断一个日期是一年中的第几天。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
classSolution { public: intdayOfYear(string date){ int days[] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; int year = stoi(date.substr(0, 4)); int month = stoi(date.substr(5,7)); int day = stoi(date.substr(8, 10)); int ans = 0; for(int i = 0; i < month; i ++) ans += days[i]; ans += day; if((year%100==0 && year%400 == 0) || (year%100 != 0 && year%4 == 0)) if(month > 2) ans += 1; return ans; } };
Leetcode1156. Swap For Longest Repeated Character Substring
You are given a string text. You can swap two of the characters in the text.
Return the length of the longest substring with repeated characters.
Example 1:
1 2 3
Input: text = "ababa" Output: 3 Explanation: We can swap the first 'b' with the last 'a', or the last 'b' with the first 'a'. Then, the longest repeated character substring is "aaa" with length 3.
Example 2:
1 2 3
Input: text = "aaabaaa" Output: 6 Explanation: Swap 'b' with the last 'a' (or the first 'a'), and we get longest repeated character substring "aaaaaa" with length 6.
Example 3:
1 2 3
Input: text = "aaaaa" Output: 5 Explanation: No need to swap, longest repeated character substring is "aaaaa" with length is 5.
classSolution { public: intmaxRepOpt1(string text){ vector<vector<pair<int, int> > > mapp(26, vector<pair<int, int>>());; int i = 0, n = text.length(); while(i < n) { int j = i+1; while(j < n && text[i] == text[j]) j ++; mapp[text[i]-'a'].push_back(make_pair(i, j-1)); i = j; } int res = 0; for (i = 0; i < 26; i ++) { if (mapp[i].size() == 0) continue; int len = mapp[i].size(); bool has_equal = len > 1; for (int j = 0; j < len; j ++) { res = max(res, mapp[i][j].second - mapp[i][j].first + 1 + has_equal); } if (len >= 2) { has_equal = len > 2; for (int j = 0; j < len-1; j ++) if (mapp[i][j+1].first - mapp[i][j].second == 2) res = max(res, mapp[i][j].second-mapp[i][j].first+1 + mapp[i][j+1].second-mapp[i][j+1].first+1 + has_equal); } } return res; } };
Leetcode1155. Number of Dice Rolls With Target Sum
You have d dice and each die has f faces numbered 1, 2, …, f.
Return the number of possible ways (out of fd total ways) modulo 109 + 7 to roll the dice so the sum of the face-up numbers equals target.
Example 1:
1 2 3 4
Input: d = 1, f = 6, target = 3 Output: 1 Explanation: You throw one die with 6 faces. There is only one way to get a sum of 3.
Example 2:
1 2 3 4 5
Input: d = 2, f = 6, target = 7 Output: 6 Explanation: You throw two dice, each with 6 faces. There are 6 ways to get a sum of 7: 1+6, 2+5, 3+4, 4+3, 5+2, 6+1.
Example 3:
1 2 3 4
Input: d = 2, f = 5, target = 10 Output: 1 Explanation: You throw two dice, each with 5 faces. There is only one way to get a sum of 10: 5+5.
Example 4:
1 2 3 4
Input: d = 1, f = 2, target = 3 Output: 0 Explanation: You throw one die with 2 faces. There is no way to get a sum of 3.
Example 5:
1 2 3 4
Input: d = 30, f = 30, target = 500 Output: 222616187 Explanation: The answer must be returned modulo 10^9 + 7.
Constraints:
1 <= d, f <= 30
1 <= target <= 1000
这道题题说是给了d个骰子,每个骰子有f个面,现在给了一个目标值 target,问同时投出这d个骰子,共有多少种组成目标值的不同组合,结果对超大数字 1e9+7 取余。首先来考虑 dp 数组该如何定义,根据硬币找零系列的启发,目标值本身肯定是占一个维度的,因为这个是要求的东西,另外就是当前骰子的个数也是要考虑的因素,所以这里使用一个二维的 dp 数组,其中dp[i][j]表示使用i个骰子组成目标值为j的所有组合个数,大小为d+1 by target+1,并初始化dp[0][0]为1。接下来就是找状态转移方程了,当前某个状态dp[i][k]跟什么相关呢,其表示为使用i个骰子组成目标值k,那么拿最后一个骰子的情况分析,其可能会投出[1,f]中的任意一个数字j,那么之前的目标值就是k-j,且用了i-1个骰子,其dp值就是dp[i-1][k-j],当前投出的点数可以跟之前所有的情况组成一种新的组合,所以当前的dp[i][k]就要加上dp[i-1][k-j],那么状态转移方程就呼之欲出了:
classSolution { public: intnumRollsToTarget(int d, int f, int target){ int M = 1e9 + 7; vector<int> dp(target + 1); dp[0] = 1; for (int i = 1; i <= d; ++i) { vector<int> t(target + 1); for (int j = 1; j <= f; ++j) { for (int k = j; k <= target; ++k) { t[k] = (t[k] + dp[k - j]) % M; } } swap(dp, t); } return dp[target]; } };
Leetcode1160. Find Words That Can Be Formed by Characters
You are given an array of strings words and a string chars.
A string is good if it can be formed by characters from chars (each character can only be used once).
Return the sum of lengths of all good strings in words.
Example 1:
1 2 3 4
Input: words = ["cat","bt","hat","tree"], chars = "atach" Output: 6 Explanation: The strings that can be formed are "cat" and "hat" so the answer is 3 + 3 = 6.
Example 2:
1 2 3 4
Input: words = ["hello","world","leetcode"], chars = "welldonehoneyr" Output: 10 Explanation: The strings that can be formed are "hello" and "world" so the answer is 5 + 5 = 10.
Note:
1 <= words.length <= 1000
1 <= words[i].length, chars.length <= 100
All strings contain lowercase English letters only.
Given the root of a binary tree, the level of its root is 1, the level of its children is 2, and so on.
Return the smallest level X such that the sum of all the values of nodes at level X is maximal.
Example 1:
1 2 3 4 5 6 7
Input: [1,7,0,7,-8,null,null] Output: 2 Explanation: Level 1 sum = 1. Level 2 sum = 7 + 0 = 7. Level 3 sum = 7 + -8 = -1. So we return the level with the maximum sum which is level 2.
classSolution { public: intmaxLevelSum(TreeNode* root){ queue<TreeNode*> q; q.push(root); int maxx = -99999; int layer = 0, max_layer = 0; while(!q.empty()){ int len = q.size(); int sum = 0; layer++; for(int i = 0; i < len; i ++){ TreeNode* temp = q.front(); q.pop(); if(temp->left != NULL) q.push(temp->left); if(temp->right != NULL) q.push(temp->right); sum += temp->val; } if(sum > maxx){ maxx = sum; max_layer = layer; } } return max_layer; } };
Leetcode1162. As Far from Land as Possible
Given an n x n grid containing only values 0 and 1, where 0 represents water and 1 represents land, find a water cell such that its distance to the nearest land cell is maximized, and return the distance. If no land or water exists in the grid, return -1.
The distance used in this problem is the Manhattan distance: the distance between two cells (x0, y0) and (x1, y1) is |x0 - x1| + |y0 - y1|.
Example 1:
1 2 3
Input: grid = [[1,0,1],[0,0,0],[1,0,1]] Output: 2 Explanation: The cell (1, 1) is as far as possible from all the land with distance 2.
Example 2:
1 2 3
Input: grid = [[1,0,0],[0,0,0],[0,0,0]] Output: 4 Explanation: The cell (2, 2) is as far as possible from all the land with distance 4.
Constraints:
n == grid.length
n == grid[i].length
1 <= n <= 100
grid[i][j] is 0 or 1
这道题给了一个只有0和1的二维数组,说是0表示水,1表示陆地,现在让找出一个0的位置,使得其离最近的1的距离最大,这里的距离用曼哈顿距离表示。这里最暴力的方法就是遍历每个0的位置,对于每个遍历到的0,再遍历每个1的位置,计算它们的距离,找到最小的距离保存为该0位置的距离,然后在所有0位置的距离中找出最大的。这种方法不是很高效,目测无法通过 OJ,博主都没有尝试。其实这道题的比较好的解法是建立距离场,即每个大于1的数字表示该位置到任意一个1位置的最短距离,在之前那道 Shortest Distance from All Buildings 就用过这种方法。建立距离场用 BFS 比较方便,因为其是一层一层往外扩散的遍历,这里需要注意的是要一次把所有1的位置都加入 queue 中一起遍历,而不是对每个1都进行 BFS,否则还是过不了 OJ。这里先把位置1都加入 queue,然后这里先做个剪枝,若位置1的个数为0,或者为 n^2,表示没有陆地,或者没有水,直接返回 -1。否则进行 while 循环,步数 step 加1,然后用 for 循环确保进行层序遍历,一定要将 q.size() 放到初始化中,因为其值可能改变。然后就是标准的 BFS 写法了,取队首元素,遍历其相邻四个结点,若没有越界且值为0,则将当前位置值更新为 step,然后将这个位置加入 queue 中继续遍历。循环退出后返回 step-1 即可,参见代码如下:
classSolution { public: intmaxDistance(vector<vector<int>>& grid){ int res = 0, n = grid.size(); for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { if (grid[i][j] == 1) continue; grid[i][j] = 201; if (i > 0) grid[i][j] = min(grid[i][j], grid[i - 1][j] + 1); if (j > 0) grid[i][j] = min(grid[i][j], grid[i][j - 1] + 1); } } for (int i = n - 1; i >= 0; --i) { for (int j = n - 1; j >= 0; --j) { if (grid[i][j] == 1) continue; if (i < n - 1) grid[i][j] = min(grid[i][j], grid[i + 1][j] + 1); if (j < n - 1) grid[i][j] = min(grid[i][j], grid[i][j + 1] + 1); res = max(res, grid[i][j]); } } return res == 201 ? -1 : res - 1; } };
Leetcode1165. Single-Row Keyboard
There is a special keyboard with all keys in a single row.
Given a string keyboard of length 26 indicating the layout of the keyboard (indexed from 0 to 25), initially your finger is at index 0. To type a character, you have to move your finger to the index of the desired character. The time taken to move your finger from index i to index j is |i - j|.
You want to type a string word. Write a function to calculate how much time it takes to type it with one finger.
Example 1:
1 2 3 4
Input: keyboard = "abcdefghijklmnopqrstuvwxyz", word = "cba" Output: 4 Explanation: The index moves from 0 to 2 to write 'c' then to 1 to write 'b' then to 0 again to write 'a'. Total time = 2 + 1 + 1 = 4.
Example 2:
1 2
Input: keyboard = "pqrstuvwxyzabcdefghijklmno", word = "leetcode" Output: 73
Constraints:
keyboard.length == 26
keyboard contains each English lowercase letter exactly once in some order.
1 <= word.length <= 10^4
word[i] is an English lowercase letter.
简单打表即可。
1 2 3 4 5 6 7 8 9 10 11 12 13
classSolution { public: intcalculateTime(string keyboard, string word){ vector<int> pos(26,-1); int k=0; for(int i=0;i<keyboard.length();i++) pos[keyboard[i]-'a'] = k++; int res=pos[word[0]-'a']; for(int i=1;i<word.length();i++) res += abs(pos[word[i]-'a']-pos[word[i-1]-'a']); return res; } };
Leetcode1170. Compare Strings by Frequency of the Smallest Character
Let’s define a function f(s) over a non-empty string s, which calculates the frequency of the smallest character in s. For example, if s = “dcce” then f(s) = 2 because the smallest character is “c” and its frequency is 2.
Now, given string arrays queries and words, return an integer array answer, where each answer[i] is the number of words such that f(queries[i]) < f(W), where W is a word in words.
Example 1:
1 2 3
Input: queries = ["cbd"], words = ["zaaaz"] Output: [1] Explanation: On the first query we have f("cbd") = 1, f("zaaaz") = 3 so f("cbd") < f("zaaaz").
Example 2:
1 2 3
Input: queries = ["bbb","cc"], words = ["a","aa","aaa","aaaa"] Output: [1,2] Explanation: On the first query only f("bbb") < f("aaaa"). On the second query both f("aaa") and f("aaaa") are both > f("cc").
Return the number of permutations of 1 to n so that prime numbers are at prime indices (1-indexed.)
(Recall that an integer is prime if and only if it is greater than 1, and cannot be written as a product of two positive integers both smaller than it.)
Since the answer may be large, return the answer modulo 10^9 + 7.
Example 1:
1 2 3
Input: n = 5 Output: 12 Explanation: For example [1,2,5,4,3] is a valid permutation, but [5,2,3,4,1] is not because the prime number 5 is at index 1.
classSolution { public: boolisprime(int n){ int nn = sqrt(n); for(int i = 2; i <= nn; i ++) { if(n % i == 0) returnfalse; } returntrue; } intnumPrimeArrangements(int n){ int count1 = 0, count2; for(int i = 2; i <= n; i ++) { if(isprime(i)) count1 ++; } count2 = n - count1; long res = 1; for(int i = 1; i <= count1; i ++) res = (res*i)%(1000000007); for(int i = 1; i <= count2; i ++) res = (res*i)%(1000000007); return res; } };
Leetcode1177. Can Make Palindrome from Substring
Given a string s, we make queries on substrings of s.
For each query queries[i] = [left, right, k], we may rearrange the substring s[left], …, s[right], and then choose up to k of them to replace with any lowercase English letter.
If the substring is possible to be a palindrome string after the operations above, the result of the query is true. Otherwise, the result is false.
Return an array answer[], where answer[i] is the result of the i-th query queries[i].
Note that: Each letter is counted individually for replacement so if for example s[left..right] = “aaa”, and k = 2, we can only replace two of the letters. (Also, note that the initial string s is never modified by any query.)
Example :
1 2 3 4 5 6 7 8
Input: s = "abcda", queries = [[3,3,0],[1,2,0],[0,3,1],[0,3,2],[0,4,1]] Output: [true,false,false,true,true] Explanation: queries[0] : substring = "d", is palidrome. queries[1] : substring = "bc", is not palidrome. queries[2] : substring = "abcd", is not palidrome after replacing only 1 character. queries[3] : substring = "abcd", could be changed to "abba" which is palidrome. Also this can be changed to "baab" first rearrange it "bacd" then replace "cd" with "ab". queries[4] : substring = "abcda", could be changed to "abcba" which is palidrome.
Constraints:
1 <= s.length, queries.length <= 10^5
0 <= queries[i][0] <= queries[i][1] < s.length
0 <= queries[i][2] <= s.length
s only contains lowercase English letters.
这道题给了一个只有小写字母的字符串s,让对s对子串进行查询。查询块包含三个信息,left,right 和k,其中 left 和 right 定义了子串的范围,k表示可以进行替换字母的个数。这里希望通过替换可以将子串变为回文串。题目中还说了可以事先给子串进行排序,这个条件一加,整个性质就不一样了,若不能排序,那么要替换的字母可能就很多了,因为对应的位置上的字母要相同才行。而能排序之后,只要把相同的字母尽可能的排列到对应的位置上,就可以减少要替换的字母,比如 hunu,若不能重排列,则至少要替换两个字母才行,而能重排顺序的话,可以先变成 uhnu,再替换中间的任意一个字母就可以了。
这里是对每个子串都建立字母出现次数的映射,所以这里用一个二维数组,大小为 n+1 by 26,因为限定了只有小写字母。然后遍历字符串s进行更新,每次先将 cnt[i+1] 赋值为 cnt[i],然后在对应的字母位置映射值自增1。累加好了之后,对于任意区间 [i, j] 的次数映射数组就可以通过 cnt[j+1] - cnt[i] 来表示,但数组之间不好直接做减法,可以再进一步访问每个字母来分别进行处理,快速得到每个字母的出现次数后除以2,将结果累加到 sum 中,就是出现奇数次字母的个数了,再除以2和k比较即可,参见代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classSolution { public: vector<bool> canMakePaliQueries(string s, vector<vector<int>>& queries){ vector<bool> res; vector<vector<int>> cnt(s.size() + 1, vector<int>(26)); for (int i = 0; i < s.size(); ++i) { cnt[i + 1] = cnt[i]; ++cnt[i + 1][s[i] - 'a']; } for (auto &query : queries) { int sum = 0; for (int i = 0; i < 26; ++i) { sum += (cnt[query[1] + 1][i] - cnt[query[0]][i]) % 2; } res.push_back(sum / 2 <= query[2]); } return res; } };
Leetcode1179. Reformat Department Table
Table: Department
1 2 3 4 5 6 7
+---------------+---------+ | Column Name | Type | +---------------+---------+ | id | int | | revenue | int | | month | varchar | +---------------+---------+
(id, month) is the primary key of this table. The table has information about the revenue of each department per month. The month has values in [“Jan”,”Feb”,”Mar”,”Apr”,”May”,”Jun”,”Jul”,”Aug”,”Sep”,”Oct”,”Nov”,”Dec”].
Write an SQL query to reformat the table such that there is a department id column and a revenue column for each month.
The query result format is in the following example:
1 2 3 4 5 6 7 8 9 10
Department table: +------+---------+-------+ | id | revenue | month | +------+---------+-------+ | 1 | 8000 | Jan | | 2 | 9000 | Jan | | 3 | 10000 | Feb | | 1 | 7000 | Feb | | 1 | 6000 | Mar | +------+---------+-------+
Note that the result table has 13 columns (1 for the department id + 12 for the months).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
# Write your MySQL query statement below select id, sum(casewhenmonth="Jan" then revenue elsenullend) as Jan_Revenue, sum(casewhenmonth= "Feb" then revenue elsenullend) as Feb_Revenue, sum(casewhenmonth= "Mar" then revenue elsenullend) as Mar_Revenue, sum(casewhenmonth= "Apr" then revenue elsenullend) as Apr_Revenue, sum(casewhenmonth= "May" then revenue elsenullend) as May_Revenue, sum(casewhenmonth= "Jun" then revenue elsenullend) as Jun_Revenue, sum(casewhenmonth= "Jul" then revenue elsenullend) as Jul_Revenue, sum(casewhenmonth= "Aug" then revenue elsenullend) as Aug_Revenue, sum(casewhenmonth= "Sep" then revenue elsenullend) as Sep_Revenue, sum(casewhenmonth= "Oct" then revenue elsenullend) as Oct_Revenue, sum(casewhenmonth= "Nov" then revenue elsenullend) as Nov_Revenue, sum(casewhenmonth= "Dec" then revenue elsenullend) as Dec_Revenue from Department groupby id orderby id
Leetcode1184. Distance Between Bus Stops
A bus has n stops numbered from 0 to n - 1 that form a circle. We know the distance between all pairs of neighboring stops where distance[i] is the distance between the stops number i and (i + 1) % n.
The bus goes along both directions i.e. clockwise and counterclockwise.
Return the shortest distance between the given start and destination stops.
Example 1:
1 2 3
Input: distance = [1,2,3,4], start = 0, destination = 1 Output: 1 Explanation: Distance between 0 and 1 is 1 or 9, minimum is 1.
Example 2:
1 2 3
Input: distance = [1,2,3,4], start = 0, destination = 2 Output: 3 Explanation: Distance between 0 and 2 is 3 or 7, minimum is 3.
Example 3:
1 2 3
Input: distance = [1,2,3,4], start = 0, destination = 3 Output: 4 Explanation: Distance between 0 and 3 is 6 or 4, minimum is 4.
Leetcode1186. Maximum Subarray Sum with One Deletion 删除一次得到子数组最大和
Given an array of integers, return the maximum sum for a non-empty subarray (contiguous elements) with at most one element deletion. In other words, you want to choose a subarray and optionally delete one element from it so that there is still at least one element left and the sum of the remaining elements is maximum possible.
Note that the subarray needs to be non-empty after deleting one element.
Example 1:
Input: arr = [1,-2,0,3] Output: 4 Explanation: Because we can choose [1, -2, 0, 3] and drop -2, thus the subarray [1, 0, 3] becomes the maximum value. Example 2:
Input: arr = [1,-2,-2,3] Output: 3 Explanation: We just choose [3] and it’s the maximum sum. Example 3:
Input: arr = [-1,-1,-1,-1] Output: -1 Explanation: The final subarray needs to be non-empty. You can’t choose [-1] and delete -1 from it, then get an empty subarray to make the sum equals to 0. Constraints:
classSolution { public: intmaxNumberOfBalloons(string text){ unordered_map<char, int> mp; for(char c : text) mp[c] ++; int aa[5] = {mp['b'], mp['a'], mp['l']/2, mp['o']/2, mp['n']}; int minn = 99999; for(int i = 0; i < 5; i ++) minn = min(minn, aa[i]); return minn; } };
Leetcode1190. Reverse Substrings Between Each Pair of Parentheses
You are given a string s that consists of lower case English letters and brackets.
Reverse the strings in each pair of matching parentheses, starting from the innermost one.
Your result should not contain any brackets.
Example 1:
1 2
Input: s = "(abcd)" Output: "dcba"
Example 2:
1 2 3
Input: s = "(u(love)i)" Output: "iloveu" Explanation: The substring "love" is reversed first, then the whole string is reversed.
Example 3:
1 2 3
Input: s = "(ed(et(oc))el)" Output: "leetcode" Explanation: First, we reverse the substring "oc", then "etco", and finally, the whole string.
Example 4:
1 2
Input: s = "a(bcdefghijkl(mno)p)q" Output: "apmnolkjihgfedcbq"
Constraints:
0 <= s.length <= 2000
s only contains lower case English characters and parentheses.
It’s guaranteed that all parentheses are balanced.
这道题给了一个只含有小写字母和括号的字符串s,现在让从最内层括号开始,每次都反转括号内的所有字符,然后可以去掉该内层括号,依次向外层类推,直到去掉所有的括号为止。可能有的童鞋拿到题后第一反应可能是递归到最内层,翻转,然后再一层一层的出来。这样的做的话就有点麻烦了,而且保不齐还有可能超时。比较好的做法就是直接遍历这个字符串,当遇到字母时,将其加入结果 res,当遇到左括号时,将当前 res 的长度加入一个数组 pos,当遇到右括号时,取出 pos 数组中的最后一个数字,并翻转 res 中该位置到结尾的所有字母,因为这个区间刚好就是当前最内层的字母,这样就能按顺序依次翻转所有括号中的内容,最终返回结果 res 即可,参见代码如下:
classSolution { public: string reverseParentheses(string s){ string res = ""; stack<int> st; int len = s.length(); for (int i = 0; i < len; i ++) if (s[i] == '(') st.push(i); elseif (s[i] == ')') { int last = st.top(); st.pop(); reverse(s.begin()+last+1, s.begin()+i); } for (int i = 0; i < len; i ++) if (s[i] != '(' && s[i] != ')') res += s[i]; return res; } };
根据k的大小,若等于1,则对原数组用 Kadane 算法,若大于1,则只拼接一个数组,那么这里就可以用 min(k, 2) 来合并这两种情况,不过在取数的时候,要用 arr[i % n] 来避免越界,这样就可以得到最大子数组之和了,不过这也还是针对 k 小于等于2的情况,对于 k 大于2的情况,还是要把减去2剩余的次数乘以整个数组之和的值加上,再一起比较,这样最终的结果就是三者之中的最大值了,参见代码如下:
1 2 3 4 5 6 7 8 9 10 11 12
classSolution { public: intkConcatenationMaxSum(vector<int>& arr, int k){ int res = INT_MIN, curSum = 0, n = arr.size(), M = 1e9 + 7; long total = accumulate(arr.begin(), arr.end(), 0); for (int i = 0; i < n * min(k, 2); ++i) { curSum = max(curSum + arr[i % n], arr[i % n]); res = max(res, curSum); } returnmax<long>({0, res, total * max(0, k - 2) + res}) % M; } };
Leetcode1192. Critical Connections in a Network
There are n servers numbered from 0 to n - 1 connected by undirected server-to-server connections forming a network where connections[i] = [ai, bi] represents a connection between servers ai and bi. Any server can reach other servers directly or indirectly through the network.
A critical connection is a connection that, if removed, will make some servers unable to reach some other server.
Return all critical connections in the network in any order.
Example 1:
1 2 3
Input: n = 4, connections = [[0,1],[1,2],[2,0],[1,3]] Output: [[1,3]] Explanation: [[3,1]] is also accepted.
Example 2:
1 2
Input: n = 2, connections = [[0,1]] Output: [[0,1]]
Constraints:
2 <= n <= 10^5
n - 1 <= connections.length <= 10^5
0 <= ai, bi <= n - 1
ai != bi
There are no repeated connections.
这道题说是有n个服务器互相连接,定义了一种关键连接,就是当去掉后,会有一部分服务无法访问另一些服务。说白了,就是让求无向图中的桥,对于求无向图中的割点或者桥的问题,需要使用塔里安算法 Tarjan’s Algorithm。该算法是图论中非常常用的算法之一,能解决强连通分量,双连通分量,割点和桥,求最近公共祖先(LCA)等问题,可以参见知乎上的这个贴子。Tarjan 算法是一种深度优先遍历 Depth-first Search 的算法,而且还带有一点联合查找 Union Find 的影子在里面。和一般的 DFS 遍历不同的是,这里用了一个类似时间戳的概念,就是用一个 time 数组来记录遍历到当前结点的时间,初始化为1,每遍历到一个新的结点,时间值就增加1。这里还用了另一个数组 low,来记录在能够访问到的所有节点中,时间戳最小的值,这样,在一个环上的结点最终 low 值都会被更新成一个最小值,就好像 Union Find 中同一个群组中都有相同的 root 值一样。这是非常重要且聪明的处理方式,因为若当前结点是割点的话,即其实桥一头的端点,当过桥之后,由于不存在其他的路径相连通(假设整个图只有一个桥),那么无法再回溯回来的,所以不管桥另一头的端点 next 的 low 值如何更新,其一定还是会大于 cur 的 low 值的,则桥就找到了。可能干讲不好理解,建议看下上面提到的知乎帖子,里面有图和视频可以很好的帮助理解。
这里首先根据给定的边来建立图的结构,这里使用 HashMap 来建立结点和其所有相连的结点集合之间的映射。对于每条边,由于是无向图,则两个方向都要建立映射,然后就调用递归,要传的参数还真不少,图结构,当前结点,前一个结点,cnt 值,time 和 low 数组,还有结果 res。在递归函数中,首先给当前结点 cur 的 time 和 low 值都赋值为 cnt,然后 cnt 自增1。接下来遍历和当前结点所有相邻的结点,若 next 的时间戳为0,表示这个结点没有被遍历过,则对该结点调用递归,然后用 next 结点的 low 值来更新当前结点的 low 值。若 next 结点已经之前访问过了,但不是前一个结点,则用 next 的 time 值来更新当前结点的 low 值。若回溯回来之后,next 的 low 值仍然大于 cur 的 time 值,说明这两个结点之间没有其他的通路,则一定是个桥,加入到结果 res 中即可,参见代码如下:
classSolution { public: vector<vector<int>> criticalConnections(int n, vector<vector<int>>& connections) { int cnt = 1; vector<vector<int>> res; vector<int> time(n), low(n); unordered_map<int, vector<int>> g; for (auto conn : connections) { g[conn[0]].push_back(conn[1]); g[conn[1]].push_back(conn[0]); } helper(g, 0, -1, cnt, time, low, res); return res; } voidhelper(unordered_map<int, vector<int>>& g, int cur, int pre, int& cnt, vector<int>& time, vector<int>& low, vector<vector<int>>& res){ time[cur] = low[cur] = cnt++; for (int next : g[cur]) { if (time[next] == 0) { helper(g, next, cur, cnt, time, low, res); low[cur] = min(low[cur], low[next]); } elseif (next != pre) { low[cur] = min(low[cur], time[next]); } if (low[next] > time[cur]) { res.push_back({cur, next}); } } } };
Leetcode1200. Minimum Absolute Difference
Given an array of distinct integers arr, find all pairs of elements with the minimum absolute difference of any two elements.
Return a list of pairs in ascending order(with respect to pairs), each pair [a, b] follows
a, b are from arr
a < b
b - a equals to the minimum absolute difference of any two elements in arr
Example 1:
1 2 3
Input: arr = [4,2,1,3] Output: [[1,2],[2,3],[3,4]] Explanation: The minimum absolute difference is 1. List all pairs with difference equal to 1 in ascending order.
Given an array A of strings made only from lowercase letters, return a list of all characters that show up in all strings within the list (including duplicates). For example, if a character occurs 3 times in all strings but not 4 times, you need to include that character three times in the final answer.
You may return the answer in any order.
Example 1:
Input: [“bella”,”label”,”roller”] Output: [“e”,”l”,”l”] Example 2:
Leetcode1003. Check If Word Is Valid After Substitutions
We are given that the string “abc” is valid.
From any valid string V, we may split V into two pieces X and Y such that X + Y (X concatenated with Y) is equal to V. (X or Y may be empty.) Then, X + “abc” + Y is also valid.
If for example S = “abc”, then examples of valid strings are: “abc”, “aabcbc”, “abcabc”, “abcabcababcc”. Examples of invalid strings are: “abccba”, “ab”, “cababc”, “bac”.
Return true if and only if the given string S is valid.
Example 1:
1 2 3 4 5
Input: "aabcbc" Output: true Explanation: We start with the valid string "abc". Then we can insert another "abc" between "a" and "bc", resulting in "a" + "abc" + "bc" which is "aabcbc".
Example 2:
1 2 3 4 5
Input: "abcabcababcc" Output: true Explanation: "abcabcabc" is valid after consecutive insertings of "abc". Then we can insert "abc" before the last letter, resulting in "abcabcab" + "abc" + "c" which is "abcabcababcc".
Example 3:
1 2
Input: "abccba" Output: false
Example 4:
1 2
Input: "cababc" Output: false
Note:
1 <= S.length <= 20000
S[i] is ‘a’, ‘b’, or ‘c’
使用 vector 来模拟栈, 当遍历访问到 c 时, 需要判断 stack 中是否已经有 a 和 b 的存在.
Given an array A of 0s and 1s, we may change up to K values from 0 to 1.
Return the length of the longest (contiguous) subarray that contains only 1s.
Example 1:
1 2 3 4 5
Input: A = [1,1,1,0,0,0,1,1,1,1,0], K = 2 Output: 6 Explanation: [1,1,1,0,0,1,1,1,1,1,1] Bolded numbers were flipped from 0 to 1. The longest subarray is underlined.
Example 2:
1 2 3 4 5
Input: A = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], K = 3 Output: 10 Explanation: [0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1] Bolded numbers were flipped from 0 to 1. The longest subarray is underlined.
用个变量 cnt 记录当前将0变为1的个数,在遍历数组的时候,若遇到了0,则 cnt 自增1。若此时 cnt 大于K了,说明该缩小窗口了,用个 while 循环,若左边界为0,移除之后,此时 cnt 应该自减1,left 自增1,每次用窗口大小更新结果 res 即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classSolution { public: intlongestOnes(vector<int>& nums, int k){ int left = 0; int cnt = 0, res = 0, len = nums.size(); for(int i = 0; i < len; i ++) { if (nums[i] == 0) cnt ++; while(cnt > k) { if (nums[left] == 0) cnt --; left ++; } res = max(res, i - left + 1); } return res; } };
我们也可以写的更简洁一些,不用 while 循环,但是还是用的滑动窗口的思路,其中i表示左边界,j为右边界。在遍历的时候,若遇到0,则K自减1,若K小于0了,且 A[i] 为0,则K自增1,且i自增1,最后返回窗口的大小即可,参见代码如下:
1 2 3 4 5 6 7 8 9 10 11
classSolution { public: intlongestOnes(vector<int>& A, int K){ int n = A.size(), i = 0, j = 0; for (; j < n; ++j) { if (A[j] == 0) --K; if (K < 0 && A[i++] == 0) ++K; } return j - i; } };
Leetcode1005. Maximize Sum Of Array After K Negations
Given an array A of integers, we must modify the array in the following way: we choose an i and replace A[i] with -A[i], and we repeat this process K times in total. (We may choose the same index i multiple times.) Return the largest possible sum of the array after modifying it in this way.
Example 1:
1 2 3
Input: A = [4,2,3], K = 1 Output: 5 Explanation: Choose indices (1,) and A becomes [4,-2,3].
Example 2:
1 2 3
Input: A = [3,-1,0,2], K = 3 Output: 6 Explanation: Choose indices (1, 2, 2) and A becomes [3,1,0,2].
Example 3:
1 2 3
Input: A = [2,-3,-1,5,-4], K = 2 Output: 13 Explanation: Choose indices (1, 4) and A becomes [2,3,-1,5,4].
classSolution { public: intlargestSumAfterKNegations(vector<int>& A, int K){ int b = 0, s = 0, length = A.size(); int i = 0, sum = 0; sort(A.begin(), A.end()); if(A[0] >= 0) { if(K % 2) A[0] = -A[0]; } else { i = 0; while(i < length && A[i] < 0 && K --) { A[i] = -A[i]; i++; } if (K > 0 && K%2 != 0) { abs(A[i]) < abs(A[i-1]) ? A[i] = -A[i] : A[i-1] = -A[i-1]; } } for(i = 0; i < length; i ++) sum += A[i]; return sum; } };
Leetcode1006. Clumsy Factorial
Normally, the factorial of a positive integer n is the product of all positive integers less than or equal to n. For example, factorial(10) = 10 9 8 7 6 5 4 3 2 * 1.
We instead make a clumsy factorial: using the integers in decreasing order, we swap out the multiply operations for a fixed rotation of operations: multiply (*), divide (/), add (+) and subtract (-) in this order.
For example, clumsy(10) = 10 9 / 8 + 7 - 6 5 / 4 + 3 - 2 * 1. However, these operations are still applied using the usual order of operations of arithmetic: we do all multiplication and division steps before any addition or subtraction steps, and multiplication and division steps are processed left to right.
Additionally, the division that we use is floor division such that 10 * 9 / 8 equals 11. This guarantees the result is an integer.
Implement the clumsy function as defined above: given an integer N, it returns the clumsy factorial of N.
classSolution { public: intclumsy(int n){ int sum = 0, i = n, j = 0; while(i > 0) { int tmp = 1; if (i != n) tmp = -1; for (j = 0; j < 4 && i > 0; j ++) { if (j == 0) tmp *= (i --); if (j == 1) tmp *= (i --); if (j == 2) tmp /= (i --); if (j == 3) tmp += (i --); } sum += tmp; if (i == 0) break; } return sum; } };
其他的做法:用个变量j来循环遍历这个数组,从而知道当前该做什么操作。还需要一个变量 cur 来计算乘和除优先级的计算,初始化为N,此时从 N-1 遍历到1,若遇到乘号,则 cur 直接乘以当前数字,若遇到除号,cur 直接除以当前数字,若遇到加号,可以直接把当前数字加到结果 res 中,若遇到减号,此时需要判断一下,因为只有第一个乘和除后的结果是要加到 res 中的,后面的都是要减去的,所以要判断一下若当前数字等于 N-4 的时候,加上 cur,否者都是减去 cur,然后 cur 更新为当前数字,因为减号的优先级小于乘除,不能立马运算。之后j自增1并对4取余,最终返回的时候也需要做个判断,因为有可能数字比较小,减号还没有出来,且此时的最后面的乘除结果还保存在 cur 中,那么是加是减还需要看N的大小,若小于等于4,则加上 cur,反之则减去 cur,参见代码如下:
classSolution { public: intclumsy(int N){ int res = 0, cur = N, j = 0; vector<char> ops{'*', '/', '+', '-'}; for (int i = N - 1; i >= 1; --i) { if (ops[j] == '*') { cur *= i; } elseif (ops[j] == '/') { cur /= i; } elseif (ops[j] == '+') { res += i; } else { res += (i == N - 4) ? cur : -cur; cur = i; } j = (j + 1) % 4; } return res + ((N <= 4) ? cur : -cur); } };
再来看一种比较简洁的写法,由于每次遇到减号时,优先级会被改变,而前面的乘除加是可以提前计算的,所以可以每次处理四个数字,即首先处理 N, N-1, N-2, N-3 这四个数字,这里希望每次可以得到乘法计算时的第一个数字,可以通过N - i*4得到,这里需要满足i*4 < N,知道了这个数字,然后可以立马算出乘除的结果,只要其大于等于3。然后需要将乘除之后的结果更新到 res 中,还是需要判断一下,若是第一个乘除的结果,需要加上,后面的都是减去。乘除后面跟的是加号,所以要加上 num-3 这个数字,前提是 num 大于3,参见代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
classSolution { public: intclumsy(int N){ int res = 0; for (int i = 0; i * 4 < N; ++i) { int num = N - i * 4, t = num; if (num >= 3) t = num * (num - 1) / (num - 2); res += (i == 0) ? t : -t; if (num > 3) res += (num - 3); } return res; } };
Leetcode1007. Minimum Domino Rotations For Equal Row
In a row of dominoes, tops[i] and bottoms[i] represent the top and bottom halves of the ith domino. (A domino is a tile with two numbers from 1 to 6 - one on each half of the tile.)
We may rotate the ith domino, so that tops[i] and bottoms[i] swap values.
Return the minimum number of rotations so that all the values in tops are the same, or all the values in bottoms are the same.
If it cannot be done, return -1.
Example 1:
1 2 3 4 5
Input: tops = [2,1,2,4,2,2], bottoms = [5,2,6,2,3,2] Output: 2 Explanation: The first figure represents the dominoes as given by tops and bottoms: before we do any rotations. If we rotate the second and fourth dominoes, we can make every value in the top row equal to 2, as indicated by the second figure.
Example 2:
1 2 3 4
Input: tops = [3,5,1,2,3], bottoms = [3,6,3,3,4] Output: -1 Explanation: In this case, it is not possible to rotate the dominoes to make one row of values equal.
Constraints:
2 <= tops.length <= 2 * 104
bottoms.length == tops.length
1 <= tops[i], bottoms[i] <= 6
这道题说是有长度相等的两个数组A和B,分别表示一排多米诺的上边数字和下边数字,多米诺的个数和数组的长度相同,数字为1到6之间,问最少旋转多少次多米诺,可以使得上边或下边的数字全部相同。例子1中给了图解,很好的帮我们理解题意,实际上出现次数越多的数字越可能就是最终全部相同的数字,所以统计A和B中每个数字出现的次数就变的很重要了,由于A和B中有可能相同位置上的是相同的数字,则不用翻转,要使得同一行变为相同的数字,翻转的地方必须是不同的数字,如何才能知道翻转后可以使同一行完全相同呢?需要某个数字在A中出现的次数加上在B中出现的次数减去A和B中相同位置出现的次数后正好等于数组的长度,这里就需要用三个数组 cntA,cntB,和 same 来分别记录某个数字在A中,B中,A和B相同位置上出现的个数,然后遍历1到6,只要符合上面提到的条件,就可以直接返回数组长度减去该数字在A和B中出现的次数中的较大值。
classSolution { public: intminDominoRotations(vector<int>& tops, vector<int>& bottoms){ int n = tops.size(), res = 0; vector<int> cnt1(7, 0), cnt2(7, 0), same(7, 0); for (int i = 0; i < n; i ++) { cnt1[tops[i]] ++; cnt2[bottoms[i]] ++; if (tops[i] == bottoms[i]) same[tops[i]] ++; }
for (int i = 1; i < 7; i ++) { if (cnt1[i] + cnt2[i] - same[i] == n) return n - max(cnt1[i], cnt2[i]); } return-1; } };
Leetcode1008. Construct Binary Search Tree from Preorder Traversal
Return the root node of a binary search tree that matches the given preorder traversal.
(Recall that a binary search tree is a binary tree where for every node, any descendant of node.left has a value < node.val, and any descendant of node.right has a value > node.val. Also recall that a preorder traversal displays the value of the node first, then traverses node.left, then traverses node.right.)
Every non-negative integer N has a binary representation. For example, 5 can be represented as “101” in binary, 11 as “1011” in binary, and so on. Note that except for N = 0, there are no leading zeroes in any binary representation.
The complement of a binary representation is the number in binary you get when changing every 1 to a 0 and 0 to a 1. For example, the complement of “101” in binary is “010” in binary.
For a given number N in base-10, return the complement of it’s binary representation as a base-10 integer.
Example 1:
1 2 3
Input: 5 Output: 2 Explanation: 5 is "101" in binary, with complement "010" in binary, which is 2 in base-10.
Example 2:
1 2 3
Input: 7 Output: 0 Explanation: 7 is "111" in binary, with complement "000" in binary, which is 0 in base-10.
Example 3:
1 2 3
Input: 10 Output: 5 Explanation: 10 is "1010" in binary, with complement "0101" in binary, which is 5 in base-10.
classSolution { public: intbitwiseComplement(int N){ if(N == 0) return1; if(N == 1) return0; vector<int> re; while(N) { re.push_back(N & 1); N = N >> 1; } reverse(re.begin(), re.end()); int res = 0; for(int i = 0; i < re.size(); i ++) { res = res * 2 + (~re[i] & 1); } return res; } };
方法二,利用位运算直接取反。
1 2 3 4 5 6 7 8 9 10 11
classSolution { public: intbitwiseComplement(int N){ int i = 0; if(!N) return1; while(N > pow(2, i)) i ++; return (~N) & ((int)pow(2, i) - 1); } };
Leetcode1010. Pairs of Songs With Total Durations Divisible by 60
In a list of songs, the i-th song has a duration of time[i] seconds.
Return the number of pairs of songs for which their total duration in seconds is divisible by 60. Formally, we want the number of indices i, j such that i < j with (time[i] + time[j]) % 60 == 0.
Example 1:
1 2 3 4 5 6
Input: [30,20,150,100,40] Output: 3 Explanation: Three pairs have a total duration divisible by 60: (time[0] = 30, time[2] = 150): total duration 180 (time[1] = 20, time[3] = 100): total duration 120 (time[1] = 20, time[4] = 40): total duration 60
Example 2:
1 2 3
Input: [60,60,60] Output: 3 Explanation: All three pairs have a total duration of 120, which is divisible by 60.
如果两首歌时间之和要能被60整除,说明余数为0,那么假设第一首歌对60的余数是 a ,那么另一首歌的对60的余数为 60-a 才行。所以我们可以用一个长度为60的数组,下标刚好对应求余后的数,每次找到一个新的歌余数为 a,就看它前面对应余数为 60-a 的有多少首歌,即可以匹配为多少对。最后这首歌的余数对应的下标数组值 ++。
这样解决之后,我们只用遍历一次数组即可,所以时间复杂度是 O(n) ,但是需要了额外的空间开销。
1 2 3 4 5 6 7 8 9 10 11 12 13
classSolution { public: intnumPairsDivisibleBy60(vector<int>& time){ int length = time.size(); int res = 0; vector<int> yushu(60, 0); for(int i = 0; i < length; i ++) { res += yushu[(60 - time[i]%60)%60]; yushu[ time[i]%60 ] ++; } return res; } };
Leetcode1011. Capacity To Ship Packages Within D Days
A conveyor belt has packages that must be shipped from one port to another within D days.
The ith package on the conveyor belt has a weight of weights[i]. Each day, we load the ship with packages on the conveyor belt (in the order given by weights). We may not load more weight than the maximum weight capacity of the ship.
Return the least weight capacity of the ship that will result in all the packages on the conveyor belt being shipped within D days.
Example 1:
1 2 3 4 5 6 7 8
Input: weights = [1,2,3,4,5,6,7,8,9,10], D = 5 Output: 15 Explanation: A ship capacity of 15 is the minimum to ship all the packages in 5 days like this: 1st day: 1, 2, 3, 4, 5 2nd day: 6, 7 3rd day: 8 4th day: 9 5th day: 10
Note that the cargo must be shipped in the order given, so using a ship of capacity 14 and splitting the packages into parts like (2, 3, 4, 5), (1, 6, 7), (8), (9), (10) is not allowed.
Example 2:
1 2 3 4 5 6
Input: weights = [3,2,2,4,1,4], D = 3 Output: 6 Explanation: A ship capacity of 6 is the minimum to ship all the packages in 3 days like this: 1st day: 3, 2 2nd day: 2, 4 3rd day: 1, 4
classSolution { public: intshipWithinDays(vector<int>& weights, int days){ int sum = 0, size = weights.size(), max_val = -1, need; for (int i = 0; i < size; i ++) { max_val = max(max_val, weights[i]); sum += weights[i]; } int left = max_val, right = sum, mid; while(left < right) { mid = left + (right - left) / 2; int cur = 0; need = 1; for (int i = 0; i < size; i ++) { if (cur + weights[i] > mid) { need ++; cur = 0; } cur += weights[i]; } if (need > days) left = mid+1; else right = mid; } return right; } };
Leetcode1013. Partition Array Into Three Parts With Equal Sum
Given an array A of integers, return true if and only if we can partition the array into three non-empty parts with equal sums.
Formally, we can partition the array if we can find indexes i+1 < j with (A[0] + A[1] + … + A[i] == A[i+1] + A[i+2] + … + A[j-1] == A[j] + A[j-1] + … + A[A.length - 1])
classSolution { public: boolcanThreePartsEqualSum(vector<int>& A){ int sum = 0, part_sum = 0, i; for(int i = 0; i < A.size(); i ++) sum += A[i]; if(sum % 3 != 0) returnfalse; sum /= 3; for(i = 0; i < A.size(); i ++) { part_sum += A[i]; if(part_sum == sum) break; } for(part_sum = 0, i = i + 1; i < A.size(); i++) { part_sum += A[i]; if(part_sum == sum) break; } if(i < A.size() - 1) returntrue; returnfalse; } };
Leetcode1014. Best Sightseeing Pair
Given an array A of positive integers, A[i] represents the value of the i-th sightseeing spot, and two sightseeing spots i and j have distance j - i between them.
The score of a pair (i < j) of sightseeing spots is (A[i] + A[j] + i - j) : the sum of the values of the sightseeing spots, minus the distance between them.
Return the maximum score of a pair of sightseeing spots.
这道题给了一个正整数的数组A,定义了一种两个数字对儿的记分方式,为A[i] + A[j] + i - j,现在让找出最大的那组的分数。利用加法的分配律,可以得到A[i] + i + A[j] - j,为了使这个表达式最大化,A[i] + i自然是越大越好,这里可以使用一个变量 mx 来记录之前出现过的A[i] + i的最大值,则当前的数字就可以当作数对儿中的另一个数字,其减去当前坐标值再加上 mx 就可以更新结果 res 了,参见代码如下:
1 2 3 4 5 6 7 8 9 10 11
classSolution { public: intmaxScoreSightseeingPair(vector<int>& values){ int maxx = INT_MIN, res = INT_MIN; for (int i = 0; i < values.size(); i ++) { res = max(res, maxx + values[i] - i); maxx = max(maxx, values[i] + i); } return res; } };
Leetcode1015. Smallest Integer Divisible by K
Given a positive integer K, you need to find the length of the smallest positive integer N such that N is divisible by K, and N only contains the digit 1.
Return the length of N. If there is no such N, return -1.
Note: N may not fit in a 64-bit signed integer.
Example 1:
1 2 3
Input: K = 1 Output: 1 Explanation: The smallest answer is N = 1, which has length 1.
Example 2:
1 2 3
Input: K = 2 Output: -1 Explanation: There is no such positive integer N divisible by 2.
Example 3:
1 2 3
Input: K = 3 Output: 3 Explanation: The smallest answer is N = 111, which has length 3.
从1开始检查,每次乘以 10 再加1,就可以得到下一个数字,但是由于K可能很大,则N就会超出整型数的范围,就算是长整型也不一定 hold 的住,所以不能一直变大,而是每次累加后都要对 K 取余,若余数为0,则直接返回当前长度,若不为0,则用余数乘以 10 再加1。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
classSolution { public: intsmallestRepunitDivByK(int k){ if (k % 2 == 0 || k % 5 == 0) return-1; int r = 0; for (int i = 1; i <= k; i ++) { r = r * 10 + 1; if (r % k == 0) return i; r = r % k; } return-1; } };
Leetcode1016. Binary String With Substrings Representing 1 To N
Given a binary string S (a string consisting only of ‘0’ and ‘1’s) and a positive integer N, return true if and only if for every integer X from 1 to N, the binary representation of X is a substring of S.
验证从N到1之间所有的数字,先求出其二进制数的字符串,在 C++ 中可以利用 bitset 来做,将其转为字符串即可。由于定义了 32 位的 bitset,转为字符串后可能会有许多 leading zeros,所以首先要移除这些0,通过在字符串中查找第一个1,然后通过取子串的函数就可以去除所有的起始0了。然后在S中查找是否存在这个二进制字符串,若不存在,直接返回 false,遍历完成后返回 true 即可,参见代码如下:
学到了,bitset还可以这么用,转成二进制字符串确实很方便。
1 2 3 4 5 6 7 8 9 10
classSolution { public: boolqueryString(string S, int N){ for (int i = N; i > 0; --i) { string b = bitset<32>(i).to_string(); if (S.find(b.substr(b.find("1"))) == string::npos) returnfalse; } returntrue; } };
Leetcode1017. Convert to Base -2
Given an integer n, return a binary string representing its representation in base -2.
Note that the returned string should not have leading zeros unless the string is “0”.
classSolution { public: string baseNeg2(int N){ string res; while (N != 0) { int rem = N % (-2); N /= -2; if (rem < 0) { rem += 2; N += 1; } res = to_string(rem) + res; } return res == "" ? "0" : res; } };
Leetcode1018. Binary Prefix Divisible By 5
Given an array A of 0s and 1s, consider N_i: the i-th subarray from A[0] to A[i] interpreted as a binary number (from most-significant-bit to least-significant-bit.)
Return a list of booleans answer, where answer[i] is true if and only if N_i is divisible by 5.
Example 1:
1 2 3
Input: [0,1,1] Output: [true,false,false] Explanation: The input numbers in binary are 0, 01, 011; which are 0, 1, and 3 in base-10. Only the first number is divisible by 5, so answer[0] is true.
由第 4 点, 可以将 number % 5 作为一个整体, 更新公式为 a = (a * 2 + A[i]) % 5.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
classSolution { public: vector<bool> prefixesDivBy5(vector<int>& A){ vector<bool> res; int ans = 0, temp = 1; for(int i = 0; i < A.size(); i ++) { ans = ((ans * 2)%5 + A[i])%5; if(ans % 5 == 0) res.push_back(true); else res.push_back(false); } return res; } };
Leetcode1019. Next Greater Node In Linked List
You are given the head of a linked list with n nodes.
For each node in the list, find the value of the next greater node. That is, for each node, find the value of the first node that is next to it and has a strictly larger value than it.
Return an integer array answer where answer[i] is the value of the next greater node of the ith node (1-indexed). If the ith node does not have a next greater node, set answer[i] = 0.
Example 1:
1 2
Input: head = [2,1,5] Output: [5,5,0]
Example 2:
1 2
Input: head = [2,7,4,3,5] Output: [7,0,5,5,0]
这道题给了一个链表,让找出每个结点值的下一个较大的结点值,跟之前的 Next Greater Element I,Next Greater Element II,和 Next Greater Element III 很类似,不同的是这里不是数组,而是链表,就稍稍的增加了一些难度,因为链表无法直接根据下标访问元素,在遍历链表之前甚至不知道总共有多少个结点。基本上来说,为了达到线性的时间复杂度,这里需要维护一个单调递减的栈,若当前的数字小于等于栈顶元素,则加入栈,若当前数字大于栈顶元素,非常棒,说明栈顶元素的下一个较大数字找到了,标记上,且把栈顶元素移除,继续判断下一个栈顶元素和当前元素的关系,直到当前数字小于等于栈顶元素为止。通过这种方法,就可以在线性的时间内找出所有数字的下一个较大的数字了。
这里新建两个数组,res 和 nums 分别保存要求的结果和链表的所有结点值,还需要一个栈 st 和一个变量 cnt(记录当前的数组坐标),然后开始遍历链表,首先把当前结点值加入数组 nums,然后开始循环,若栈不空,且当前结点值大于栈顶元素(注意这里单调栈存的并不是结点值,而是该值在 nums 数组中的坐标值,这是为了更好的在结果 res 中定位),此时用该结点值来更新结果 res 中的对应的位置,然后将栈顶元素移除,继续循环直到条件不满足位置。然后把当前的坐标加入栈中,此时还要更新结果 res 的大小,因为由于链表的大小未知,无法直接初始化 res 的大小,当然我们可以在开头的时候先遍历一遍链表,得到结点的个数也是可以的,参见代码如下:
Given a 2D array A, each cell is 0 (representing sea) or 1 (representing land)
A move consists of walking from one land square 4-directionally to another land square, or off the boundary of the grid.
Return the number of land squares in the grid for which we cannot walk off the boundary of the grid in any number of moves.
Example 1:
1 2 3 4
Input: [[0,0,0,0],[1,0,1,0],[0,1,1,0],[0,0,0,0]] Output: 3 Explanation: There are three 1s that are enclosed by 0s, and one 1 that isn't enclosed because its on the boundary.
Example 2:
1 2 3 4
Input: [[0,1,1,0],[0,0,1,0],[0,0,1,0],[0,0,0,0]] Output: 0 Explanation: All 1s are either on the boundary or can reach the boundary.
Note:
1 <= A.length <= 500
1 <= A[i].length <= 500
0 <= A[i][j] <= 1
All rows have the same size.
这道题给了一个只有0和1的二维数组A,其中0表示海洋,1表示陆地,每次只能从一块陆地走到和其相连的另一块陆地上,问有多少块陆地可以不用走到边界上。其实这道题就是让找出被0完全包围的1的个数,反过来想,如果有1在边界上,那么和其相连的所有1都是不符合题意的,所以只要以边界上的1为起点,遍历所有和其相连的1,并且标记,则剩下的1一定就是被0完全包围的。遍历的方法可以用 BFS 或者 DFS,先来看 BFS 的解法,使用一个队列 queue,遍历数组A,现将所有1的个数累加到结果 res,然后将边界上的1的坐标加入队列中。然后开始 while 循环,去除队首元素,若越界了,或者对应的值不为1,直接跳过。否则标记当前位置值为0,并且 res 自减1,然后将周围四个位置都排入队列中,最后返回结果 res 即可,参见代码如下:
classSolution { public: voiddfs(vector<vector<int>>& grid, int i, int j){ if (i < 0 || i >= grid.size() || j < 0 || j >= grid[0].size() || grid[i][j] != 1) return; grid[i][j] = 0; dfs(grid, i, j+1); dfs(grid, i, j-1); dfs(grid, i+1, j); dfs(grid, i-1, j); } intnumEnclaves(vector<vector<int>>& grid){ int m = grid.size(), n = grid[0].size(), num1 = 0; for (int i = 0; i < m; i ++) { if (grid[i][0] == 1) dfs(grid, i, 0); if (grid[i][n-1] == 1) dfs(grid, i, n-1); } for (int i = 0; i < n; i ++) { if (grid[0][i] == 1) dfs(grid, 0, i); if (grid[m-1][i] == 1) dfs(grid, m-1, i); } for (int i = 0; i < m; i ++) for (int j = 0; j < n; j ++) if (grid[i][j] == 1) num1 ++; return num1; } };
Leetcode1021. Remove Outermost Parentheses
A valid parentheses string is either empty (“”), “(“ + A + “)”, or A + B, where A and B are valid parentheses strings, and + represents string concatenation. For example, “”, “()”, “(())()”, and “(()(()))” are all valid parentheses strings.
A valid parentheses string S is primitive if it is nonempty, and there does not exist a way to split it into S = A+B, with A and B nonempty valid parentheses strings.
Given a valid parentheses string S, consider its primitive decomposition: S = P_1 + P_2 + … + P_k, where P_i are primitive valid parentheses strings.
Return S after removing the outermost parentheses of every primitive string in the primitive decomposition of S.
Example 1:
1 2 3 4 5
Input: "(()())(())" Output: "()()()" Explanation: The input string is "(()())(())", with primitive decomposition "(()())" + "(())". After removing outer parentheses of each part, this is "()()" + "()" = "()()()".
Example 2:
1 2 3 4 5
Input: "(()())(())(()(()))" Output: "()()()()(())" Explanation: The input string is "(()())(())(()(()))", with primitive decomposition "(()())" + "(())" + "(()(()))". After removing outer parentheses of each part, this is "()()" + "()" + "()(())" = "()()()()(())".
Example 3:
1 2 3 4 5
Input: "()()" Output: "" Explanation: The input string is "()()", with primitive decomposition "()" + "()". After removing outer parentheses of each part, this is "" + "" = "".
Given a binary tree, each node has value 0 or 1. Each root-to-leaf path represents a binary number starting with the most significant bit. For example, if the path is 0 -> 1 -> 1 -> 0 -> 1, then this could represent 01101 in binary, which is 13.
For all leaves in the tree, consider the numbers represented by the path from the root to that leaf.
classSolution { public: int result; voiddfs(TreeNode* root ,int now){ if(!root->left && !root->right){ result += (now<<1) + root->val; } int val = (now<<1) + root->val; if(root->left) dfs(root->left, val); if(root->right) dfs(root->right, val); } intsumRootToLeaf(TreeNode* root){ result=0; dfs(root,0); return result; } };
Leetcode1023. Camelcase Matching
A query word matches a given pattern if we can insert lowercase letters to the pattern word so that it equals the query. (We may insert each character at any position, and may insert 0 characters.)
Given a list of queries, and a pattern, return an answer list of booleans, where answer[i] is true if and only if queries[i] matches the pattern.
Example 1:
1 2 3 4 5 6
Input: queries = ["FooBar","FooBarTest","FootBall","FrameBuffer","ForceFeedBack"], pattern = "FB" Output: [true,false,true,true,false] Explanation: "FooBar" can be generated like this "F" + "oo" + "B" + "ar". "FootBall" can be generated like this "F" + "oot" + "B" + "all". "FrameBuffer" can be generated like this "F" + "rame" + "B" + "uffer".
Example 2:
1 2 3 4 5
Input: queries = ["FooBar","FooBarTest","FootBall","FrameBuffer","ForceFeedBack"], pattern = "FoBa" Output: [true,false,true,false,false] Explanation: "FooBar" can be generated like this "Fo" + "o" + "Ba" + "r". "FootBall" can be generated like this "Fo" + "ot" + "Ba" + "ll".
Example 3:
1 2 3 4
Input: queries = ["FooBar","FooBarTest","FootBall","FrameBuffer","ForceFeedBack"], pattern = "FoBaT" Output: [false,true,false,false,false] Explanation: "FooBarTest" can be generated like this "Fo" + "o" + "Ba" + "r" + "T" + "est".
Note:
1 <= queries.length <= 100
1 <= queries[i].length <= 100
1 <= pattern.length <= 100
All strings consists only of lower and upper case English letters.
Solution 1, Find For each query, find all letters in pattern left-to-right. If we found all pattern letters, check that the rest of the letters is in the lower case.
For simplicity, we can replace the found pattern letter in query with a lowercase ‘a’.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
vector<bool> camelMatch(vector<string>& qs, string pattern, vector<bool> res = {}){ for (auto i = 0; i < qs.size(); ++i) { for (auto p = -1, j = 0; j < pattern.size(); ++j) { p = qs[i].find(pattern[j], p + 1); if (p == string::npos) { res.push_back(false); break; } qs[i][p] = 'a'; } if (res.size() <= i) res.push_back(all_of(begin(qs[i]), end(qs[i]), [](char ch) { returnislower(ch); })); } return res; }
Solution 2, Simple Scan Instead of using the find function, we can just check all characters in the query. If a character matches the pattern pointer (pattern[p]), we advance that pointer (++p). Otherwise, we check that the query character is in the lower case.
检查查询的字符串,如果一个字符与pattern[p]匹配了,就继续,如果不匹配,看是不是小些
With this solution, it’s also easer to realize that the complexity is O(n), where n is the total number of query characters.
1 2 3 4 5 6 7 8 9 10
vector<bool> camelMatch(vector<string>& qs, string pattern, vector<bool> res = {}){ for (auto i = 0, j = 0, p = 0; i < qs.size(); ++i) { for (j = 0, p = 0; j < qs[i].size(); ++j) { if (p < pattern.size() && qs[i][j] == pattern[p]) ++p; elseif (!islower(qs[i][j])) break; } res.push_back(j == qs[i].size() && p == pattern.size()); } return res; }
Complexity Analysis
Runtime: O(n), where n is all letters in all queries. We process each letter only once.
Memory: O(m), where m is the number of queries (to store the result).
时间复杂度O(n),空间复杂度O(m)
Leetcode1024. Video Stitching
You are given a series of video clips from a sporting event that lasted T seconds. These video clips can be overlapping with each other and have varied lengths.
Each video clip clips[i] is an interval: it starts at time clips[i][0] and ends at time clips[i][1]. We can cut these clips into segments freely: for example, a clip [0, 7] can be cut into segments [0, 1] + [1, 3] + [3, 7].
Return the minimum number of clips needed so that we can cut the clips into segments that cover the entire sporting event ([0, T]). If the task is impossible, return -1.
Input: clips = [[0,2],[4,6],[8,10],[1,9],[1,5],[5,9]], T = 10 Output: 3 Explanation: We take the clips [0,2], [8,10], [1,9]; a total of 3 clips. Then, we can reconstruct the sporting event as follows: We cut [1,9] into segments [1,2] + [2,8] + [8,9]. Now we have segments [0,2] + [2,8] + [8,10] which cover the sporting event [0, 10].
Example 2:
1 2 3 4
Input: clips = [[0,1],[1,2]], T = 5 Output: -1 Explanation: We can't cover [0,5] with only [0,1] and [0,2].
Example 3:
1 2 3 4
Input: clips = [[0,1],[6,8],[0,2],[5,6],[0,4],[0,3],[6,7],[1,3],[4,7],[1,4],[2,5],[2,6],[3,4],[4,5],[5,7],[6,9]], T = 9 Output: 3 Explanation: We can take clips [0,4], [4,7], and [6,9].
Example 4:
1 2 3 4
Input: clips = [[0,4],[2,8]], T = 5 Output: 2 Explanation: Notice you can have extra video after the event ends.
Alice and Bob take turns playing a game, with Alice starting first.
Initially, there is a number N on the chalkboard. On each player’s turn, that player makes a move consisting of:
Choosing any x with 0 < x < N and N % x == 0. Replacing the number N on the chalkboard with N - x. Also, if a player cannot make a move, they lose the game.
Return True if and only if Alice wins the game, assuming both players play optimally.
Example 1:
1 2 3
Input: 2 Output: true Explanation: Alice chooses 1, and Bob has no more moves.
Example 2:
1 2 3
Input: 3 Output: false Explanation: Alice chooses 1, Bob chooses 1, and Alice has no more moves.
Note:
1 <= N <= 1000
两个人玩游戏,给一个数字N,先轮到A走,A选一个数字x使得0 < x < N且N % x == 0,之后N变为N-x,如果谁选不出来x,那就输了,A遇见偶数赢,奇数输。
Leetcode1026. Maximum Difference Between Node and Ancestor
Given the root of a binary tree, find the maximum value V for which there exists different nodes A and B where V = |A.val - B.val| and A is an ancestor of B.
(A node A is an ancestor of B if either: any child of A is equal to B, or any child of A is an ancestor of B.)
Example 1:
1 2 3 4 5 6 7 8 9
Input: [8,3,10,1,6,null,14,null,null,4,7,13] Output: 7 Explanation: We have various ancestor-node differences, some of which are given below : |8 - 3| = 5 |3 - 7| = 4 |8 - 1| = 7 |10 - 13| = 3 Among all possible differences, the maximum value of 7 is obtained by |8 - 1| = 7.
Note:
The number of nodes in the tree is between 2 and 5000.
Given an array A of integers, return the length of the longest arithmetic subsequence in A.
Recall that a subsequence of A is a list A[i_1], A[i_2], …, A[i_k] with 0 <= i_1 < i_2 < … < i_k <= A.length - 1, and that a sequence B is arithmetic if B[i+1] - B[i] are all the same value (for 0 <= i < B.length - 1).
Example 1:
1 2 3 4
Input: A = [3,6,9,12] Output: 4 Explanation: The whole array is an arithmetic sequence with steps of length = 3.
Example 2:
1 2 3 4
Input: A = [9,4,7,2,10] Output: 3 Explanation: The longest arithmetic subsequence is [4,7,10].
Example 3:
1 2 3 4
Input: A = [20,1,15,3,10,5,8] Output: 4 Explanation: The longest arithmetic subsequence is [20,15,10,5].
classSolution { public: intlongestArithSeqLength(vector<int>& A){ int res = 0, n = A.size(); vector<vector<int>> dp(n, vector<int>(2000)); for (int i = 0; i < n; ++i) { for (int j = 0; j < i; ++j) { int diff = A[i] - A[j] + 1000; dp[i][diff] = dp[j][diff] + 1; res = max(res, dp[i][diff]); } } return res + 1; } };
Leetcode1028. Recover a Tree From Preorder Traversal
We run a preorder depth-first search (DFS) on the root of a binary tree.
At each node in this traversal, we output D dashes (where D is the depth of this node), then we output the value of this node. If the depth of a node is D, the depth of its immediate child is D + 1. The depth of the root node is 0.
If a node has only one child, that child is guaranteed to be the left child.
Given the output traversal of this traversal, recover the tree and return its root.
遍历输入字符串,先提取短杠的个数,因为除了根结点之外,所有的深度值都是在结点值前面的,所有用一个 for 循环先提取出短杠的个数 level,然后提取结点值,也是用一个 for 循环,因为结点值可能是个多位数,有了结点值之后我们就可以新建一个结点了。下一步就比较 tricky 了,因为先序遍历跟 DFS 搜索一样有一个回到先前位置的过程,比如例子1中,当我们遍历到结点5的时候,此时是从叶结点4回到了根结点的右子结点5,现在栈中有4个结点,而当前深度为1的结点5是要连到根结点的,所以栈中的无关结点就要移除,需要把结点 2,3,4 都移除,就用一个 while 循环,假如栈中元素个数大于当前的深度 level,就移除栈顶元素。那么此时栈中就只剩根结点了,就可以连接了。此时我们的连接策略是,假如栈顶元素的左子结点为空,则连在左子结点上,否则连在右子结点上,因为题目中说了,假如只有一个子结点,一定是左子结点。然后再把当前结点压入栈即可,字符串遍历结束后,栈中只会留有一个结点(题目中限定了树不为空),就是根结点,直接返回即可,参见代码如下:
classSolution { public: TreeNode* dfs(string s, int& cur, int depth){ if (cur == s.length()) returnNULL; int i = cur, len = s.length(); while(i < len && i < cur+depth) { if (s[i] != '-') break; i ++; } if (i != cur+depth) returnNULL; int val = 0; while(i < len) if ('0' <= s[i] && s[i] <= '9') val = val * 10 + s[i++] - '0'; else break; TreeNode* res = newTreeNode(val); cur = i; res->left = dfs(s, cur, depth+1); res->right = dfs(s, cur, depth+1); return res; } TreeNode* recoverFromPreorder(string s){ int pos = 0; returndfs(s, pos, 0); } };
Leetcode1029. Two City Scheduling
There are 2N people a company is planning to interview. The cost of flying the i-th person to city A is costs[i][0], and the cost of flying the i-th person to city B is costs[i][1].
Return the minimum cost to fly every person to a city such that exactly N people arrive in each city.
Example 1:
1 2 3 4 5 6 7
Input: [[10,20],[30,200],[400,50],[30,20]] Output: 110 Explanation: The first person goes to city A for a cost of 10. The second person goes to city A for a cost of 30. The third person goes to city B for a cost of 50. The fourth person goes to city B for a cost of 20.
The total minimum cost is 10 + 30 + 50 + 20 = 110 to have half the people interviewing in each city.
Note:
1 <= costs.length <= 100
It is guaranteed that costs.length is even.
1 <= costs[i][0], costs[i][1] <= 1000
公司计划面试 2N 人。第 i 人飞往 A 市的费用为 costs[i][0],飞往 B 市的费用为 costs[i][1]。 返回将每个人都飞到某座城市的最低费用,要求每个城市都有 N 人抵达。
classSolution { public: staticboolcomp(vector<int>&a, vector<int>&b){ return a[0]-a[1] < b[0]-b[1]; } inttwoCitySchedCost(vector<vector<int>>& costs){ int result=0; if(costs.size()==0) return result; sort(costs.begin(), costs.end(), comp); int ii=costs.size(); int i; for(i=0;i<ii/2;i++) result += costs[i][0]; for(;i<ii;i++) result+=costs[i][1]; return result; } };
Leetcode1030. Matrix Cells in Distance Order
We are given a matrix with R rows and C columns has cells with integer coordinates (r, c), where 0 <= r < R and 0 <= c < C.
Additionally, we are given a cell in that matrix with coordinates (r0, c0).
Return the coordinates of all cells in the matrix, sorted by their distance from (r0, c0) from smallest distance to largest distance. Here, the distance between two cells (r1, c1) and (r2, c2) is the Manhattan distance, |r1 - r2| + |c1 - c2|. (You may return the answer in any order that satisfies this condition.)
Example 1:
1 2 3
Input: R = 1, C = 2, r0 = 0, c0 = 0 Output: [[0,0],[0,1]] Explanation: The distances from (r0, c0) to other cells are: [0,1]
Example 2:
1 2 3 4
Input: R = 2, C = 2, r0 = 0, c0 = 1 Output: [[0,1],[0,0],[1,1],[1,0]] Explanation: The distances from (r0, c0) to other cells are: [0,1,1,2] The answer [[0,1],[1,1],[0,0],[1,0]] would also be accepted as correct.
Example 3:
1 2 3 4
Input: R = 2, C = 3, r0 = 1, c0 = 2 Output: [[1,2],[0,2],[1,1],[0,1],[1,0],[0,0]] Explanation: The distances from (r0, c0) to other cells are: [0,1,1,2,2,3] There are other answers that would also be accepted as correct, such as [[1,2],[1,1],[0,2],[1,0],[0,1],[0,0]].
classSolution { public: staticboolcomp(vector<int>& a, vector<int>& b){ return a[2] < b[2]; } vector<vector<int>> allCellsDistOrder(int R, int C, int r0, int c0) { int k = 0; vector<vector<int>> v(R*C, vector<int>(3)); for (int i = 0; i < R; i ++) { for(int j = 0; j < C; j ++) { v[k][0] = i; v[k][1] = j; v[k][2] = abs(i - r0) + abs(j - c0); k ++; } } sort(v.begin(), v.end(), comp); for(int kk = 0; kk < R*C; kk ++) { v[kk].pop_back(); } return v; } };
Leetcode1031. Maximum Sum of Two Non-Overlapping Subarrays
Given an integer array nums and two integers firstLen and secondLen, return the maximum sum of elements in two non-overlapping subarrays with lengths firstLen and secondLen.
The array with length firstLen could occur before or after the array with length secondLen, but they have to be non-overlapping.
A subarray is a contiguous part of an array.
Example 1:
1 2 3
Input: nums = [0,6,5,2,2,5,1,9,4], firstLen = 1, secondLen = 2 Output: 20 Explanation: One choice of subarrays is [9] with length 1, and [6,5] with length 2.
Example 2:
1 2 3
Input: nums = [3,8,1,3,2,1,8,9,0], firstLen = 3, secondLen = 2 Output: 29 Explanation: One choice of subarrays is [3,8,1] with length 3, and [8,9] with length 2.
Example 3:
1 2 3
Input: nums = [2,1,5,6,0,9,5,0,3,8], firstLen = 4, secondLen = 3 Output: 31 Explanation: One choice of subarrays is [5,6,0,9] with length 4, and [3,8] with length 3.
classSolution { public: intmaxSumTwoNoOverlap(vector<int>& nums, int l, int m){ int n = nums.size(), res = 0; vector<int> sum(n, 0); vector<vector<int>> dp(n, vector<int>(2, 0)); for (int i = 0; i < n; i ++) { for (int j = 0; j < l && i+j < n; j ++) dp[i][0] += nums[i+j]; for (int j = 0; j < m && i+j < n; j ++) dp[i][1] += nums[i+j]; } for (int i = 0; i < n; i ++) { for (int j = 0; j < n; j ++) { if (i + l <= j) res = max(res, dp[i][0]+dp[j][1]); if (j + m <= i) res = max(res, dp[i][0]+dp[j][1]); } } return res; } };
classSolution { public: intmaxSumTwoNoOverlap(vector<int>& A, int L, int M){ for (int i = 1; i < A.size(); ++i) { A[i] += A[i - 1]; } int res = A[L + M - 1], Lmax = A[L - 1], Mmax = A[M - 1]; for (int i = L + M; i < A.size(); ++i) { Lmax = max(Lmax, A[i - M] - A[i - M - L]); Mmax = max(Mmax, A[i - L] - A[i - M - L]); res = max(res, max(Lmax + A[i] - A[i - M], Mmax + A[i] - A[i - L])); } return res; } };
Leetcode1033. Moving Stones Until Consecutive
Three stones are on a number line at positions a, b, and c. Each turn, you pick up a stone at an endpoint (ie., either the lowest or highest position stone), and move it to an unoccupied position between those endpoints. Formally, let’s say the stones are currently at positions x, y, z with x < y < z. You pick up the stone at either position x or position z, and move that stone to an integer position k, with x < k < z and k != y. The game ends when you cannot make any more moves, ie. the stones are in consecutive positions.
When the game ends, what is the minimum and maximum number of moves that you could have made? Return the answer as an length 2 array: answer = [minimum_moves, maximum_moves]
Example 1:
1 2 3
Input: a = 1, b = 2, c = 5 Output: [1,2] Explanation: Move the stone from 5 to 3, or move the stone from 5 to 4 to 3.
Example 2:
1 2 3
Input: a = 4, b = 3, c = 2 Output: [0,0] Explanation: We cannot make any moves.
Example 3:
1 2 3
Input: a = 3, b = 5, c = 1 Output: [1,2] Explanation: Move the stone from 1 to 4; or move the stone from 1 to 2 to 4.
classSolution { public: vector<int> numMovesStones(int a, int b, int c){ int sum_ = a + b + c; int min_ = min(a, min(b, c)); int max_ = max(a, max(b, c)); int mid_ = sum_ - min_ - max_; if (max_ - min_ == 2) return {0, 0}; int min_move = min(mid_ - min_, max_ - mid_) <= 2 ? 1 : 2; int max_move = max_ - min_ - 2; return {min_move, max_move}; } };
Leetcode1034. Coloring A Border
Given a 2-dimensional grid of integers, each value in the grid represents the color of the grid square at that location.
Two squares belong to the same connected component if and only if they have the same color and are next to each other in any of the 4 directions.
The border of a connected component is all the squares in the connected component that are either 4-directionally adjacent to a square not in the component, or on the boundary of the grid (the first or last row or column).
Given a square at location (r0, c0) in the grid and a color, color the border of the connected component of that square with the given color, and return the final grid.
classSolution { public: vector<vector<int>> colorBorder(vector<vector<int>>& grid, int row, int col, int color) { int m = grid.size(), n = grid[0].size(), ori_color = grid[row][col]; vector<vector<int>> visited(m, vector<int>(n, 0)); vector<vector<int>> dirs{{-1, 0}, {0, 1}, {1, 0}, {0, -1}} ; queue<int> q; q.push(row*n + col); visited[row][col] = 1; while(!q.empty()) { int x = q.front() / n; int y = q.front() % n; q.pop(); if (x == 0 || x == m-1 || y == 0 || y == n-1) grid[x][y] = color; for (int i = 0; i < 4; i ++) { int xx = x + dirs[i][0]; int yy = y + dirs[i][1]; if (xx < 0 || xx >= m || yy < 0 || yy >= n || visited[xx][yy] == 1) continue; if (grid[xx][yy] == ori_color) { q.push(xx * n + yy); visited[xx][yy] = 1; } else grid[x][y] = color; } } return grid; } };
Leetcode1035. Uncrossed Lines
We write the integers of A and B (in the order they are given) on two separate horizontal lines.
Now, we may draw connecting lines : a straight line connecting two numbers A[i] and B[j] such that:A[i] == B[j];
The line we draw does not intersect any other connecting (non-horizontal) line.
Note that a connecting lines cannot intersect even at the endpoints: each number can only belong to one connecting line.
Return the maximum number of connecting lines we can draw in this way.
Example 1:
1 2 3 4
Input: A = [1,4,2], B = [1,2,4] Output: 2 Explanation: We can draw 2 uncrossed lines as in the diagram. We cannot draw 3 uncrossed lines, because the line from A[1]=4 to B[2]=4 will intersect the line from A[2]=2 to B[1]=2.
Example 2:
1 2
Input: A = [2,5,1,2,5], B = [10,5,2,1,5,2] Output: 3
Example 3:
1 2
Input: A = [1,3,7,1,7,5], B = [1,9,2,5,1] Output: 2
classSolution { public: intmaxUncrossedLines(vector<int>& A, vector<int>& B) { int m = A.size(), n = B.size(); vector<vector<int>> dp(m + 1, vector<int>(n + 1)); for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { if (A[i - 1] == B[j - 1]) { dp[i][j] = dp[i - 1][j - 1] + 1; } else { dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); } } } return dp[m][n]; } };
Leetcode1037. Valid Boomerang
A boomerang is a set of 3 points that are all distinct and not in a straight line. Given a list of three points in the plane, return whether these points are a boomerang.
Leetcode1038. Binary Search Tree to Greater Sum Tree
Given the root of a binary search tree with distinct values, modify it so that every node has a new value equal to the sum of the values of the original tree that are greater than or equal to node.val.
As a reminder, a binary search tree is a tree that satisfies these constraints:
The left subtree of a node contains only nodes with keys less than the node’s key. The right subtree of a node contains only nodes with keys greater than the node’s key. Both the left and right subtrees must also be binary search trees.
Leetcode1039. Minimum Score Triangulation of Polygon
You have a convex n-sided polygon where each vertex has an integer value. You are given an integer array values where values[i] is the value of the ith vertex (i.e., clockwise order).
You will triangulate the polygon into n - 2 triangles. For each triangle, the value of that triangle is the product of the values of its vertices, and the total score of the triangulation is the sum of these values over all n - 2 triangles in the triangulation.
Return the smallest possible total score that you can achieve with some triangulation of the polygon.
Example 1:
1 2 3
Input: values = [1,2,3] Output: 6 Explanation: The polygon is already triangulated, and the score of the only triangle is 6.
Example 2:
1 2 3 4
Input: values = [3,7,4,5] Output: 144 Explanation: There are two triangulations, with possible scores: 3*7*5 + 4*5*7 = 245, or 3*4*5 + 3*4*7 = 144. The minimum score is 144.
classSolution { public: intminScoreTriangulation(vector<int>& A){ int n = A.size(); vector<vector<int>> dp(n, vector<int>(n)); for (int len = 2; len < n; ++len) { for (int i = 0; i + len < n; ++i) { int j = i + len; dp[i][j] = INT_MAX; for (int k = i + 1; k < j; ++k) { dp[i][j] = min(dp[i][j], dp[i][k] + A[i] * A[k] * A[j] + dp[k][j]); } } } return dp[0][n - 1]; } };
Leetcode1041. Robot Bounded In Circle
On an infinite plane, a robot initially stands at (0, 0) and faces north. The robot can receive one of three instructions:
“G”: go straight 1 unit;
“L”: turn 90 degrees to the left;
“R”: turn 90 degrees to the right.
The robot performs the instructions given in order, and repeats them forever.
Return true if and only if there exists a circle in the plane such that the robot never leaves the circle.
Example 1:
1 2 3 4
Input: instructions = "GGLLGG" Output: true Explanation: The robot moves from (0,0) to (0,2), turns 180 degrees, and then returns to (0,0). When repeating these instructions, the robot remains in the circle of radius 2 centered at the origin.
Example 2:
1 2 3
Input: instructions = "GG" Output: false Explanation: The robot moves north indefinitely.
classSolution { public: boolisRobotBounded(string instructions){ vector<vector<int>> dirs{{0, 1}, {-1, 0}, {0, -1}, {1, 0}}; int xx = 0, yy = 0; int direction = 0; for (int i = 0; i < instructions.size(); i ++) { if (instructions[i] == 'G') { xx += dirs[direction][0]; yy += dirs[direction][1]; } elseif (instructions[i] == 'L') direction = (direction + 1 ) % 4; elseif (instructions[i] == 'R') direction = (direction + 4 - 1) % 4; } return (xx == 0 && yy == 0) || direction != 0; } };
Leetcode1042. Flower Planting With No Adjacent
You have N gardens, labelled 1 to N. In each garden, you want to plant one of 4 types of flowers. paths[i] = [x, y] describes the existence of a bidirectional path from garden x to garden y. Also, there is no garden that has more than 3 paths coming into or leaving it.
Your task is to choose a flower type for each garden such that, for any two gardens connected by a path, they have different types of flowers.
Return any such a choice as an array answer, where answer[i] is the type of flower planted in the (i+1)-th garden. The flower types are denoted 1, 2, 3, or 4. It is guaranteed an answer exists.
Example 1:
1 2
Input: N = 3, paths = [[1,2],[2,3],[3,1]] Output: [1,2,3]
Example 2:
1 2
Input: N = 4, paths = [[1,2],[3,4]] Output: [1,2,1,2]
Example 3:
1 2
Input: N = 4, paths = [[1,2],[2,3],[3,4],[4,1],[1,3],[2,4]] Output: [1,2,3,4]
Note:
1 <= N <= 10000
0 <= paths.size <= 20000
No garden has 4 or more paths coming into or leaving it.
It is guaranteed an answer exists.
有 N 个花园,按从 1 到 N 标记。在每个花园中,你打算种下四种花之一。 paths[i] = [x, y] 描述了花园 x 到花园 y 的双向路径。另外,没有花园有 3 条以上的路径可以进入或者离开。你需要为每个花园选择一种花,使得通过路径相连的任何两个花园中的花的种类互不相同。以数组形式返回选择的方案作为答案 answer,其中 answer[i] 为在第 (i+1) 个花园中种植的花的种类。花的种类用 1, 2, 3, 4 表示。保证存在答案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classSolution { public: vector<int> gardenNoAdj(int N, vector<vector<int>>& paths){ vector<int> res(N, 0); vector<vector<int>> graph(N); for(int i = 0 ; i < paths.size(); i ++) { graph[paths[i][0]-1].push_back(paths[i][1]-1); graph[paths[i][1]-1].push_back(paths[i][0]-1); } for (int i = 0; i < N; ++i) { int mask = 0; for (constauto& j : graph[i]) mask |= (1 << res[j]); for (int c = 1; c <= 4 && res[i] == 0; ++c) if (!(mask & (1 << c))) res[i] = c; } return res; } };
Leetcode1043. Partition Array for Maximum Sum
Given an integer array arr, you should partition the array into (contiguous) subarrays of length at most k. After partitioning, each subarray has their values changed to become the maximum value of that subarray.
Return the largest sum of the given array after partitioning.
classSolution { public: intmaxSumAfterPartitioning(vector<int>& arr, int k){ int n = arr.size(); vector<int> dp(n + 1); for (int i = 1; i <= n; ++i) { int curMax = 0; for (int j = 1; j <= k && i - j >= 0; ++j) { curMax = max(curMax, arr[i - j]); dp[i] = max(dp[i], dp[i - j] + curMax * j); } } return dp[n]; } };
Leetcode1046. Last Stone Weight
We have a collection of stones, each stone has a positive integer weight.
Each turn, we choose the two heaviest stones and smash them together. Suppose the stones have weights x and y with x <= y. The result of this smash is:
If x == y, both stones are totally destroyed;
If x != y, the stone of weight x is totally destroyed, and the stone of weight y has new weight y-x.
At the end, there is at most 1 stone left. Return the weight of this stone (or 0 if there are no stones left.)
Example 1:
1 2 3 4 5 6 7
Input: [2,7,4,1,8,1] Output: 1 Explanation: We combine 7 and 8 to get 1 so the array converts to [2,4,1,1,1] then, we combine 2 and 4 to get 2 so the array converts to [2,1,1,1] then, we combine 2 and 1 to get 1 so the array converts to [1,1,1] then, we combine 1 and 1 to get 0 so the array converts to [1] then that's the value of last stone.
classSolution { public: intlastStoneWeight(vector<int>& stones){ int p, q; if(stones.size() == 1) return stones[0]; while(stones.size() >= 2) { heapsort(stones); p = stones.back(); stones.pop_back(); q = stones.back(); stones.pop_back(); int diff = p - q; if(diff) stones.push_back(diff); } if(stones.empty()) return0; return stones[0]; } voidheapsort(vector<int>& stones){ if(stones.size() <= 1) return; build_heap(stones); int heap_size = stones.size(); while(heap_size >= 2) { swap(stones[0], stones[heap_size - 1]); heap_size --; max_heapify(stones, 0, heap_size); } } voidbuild_heap(vector<int>& stones){ for(int i=stones.size()/2; i>=0; i--){ max_heapify(stones, i, stones.size()); } } voidmax_heapify(vector<int>& stones, int i, int heap_size){ int large = i; if(2*i+1<heap_size && stones[i]<stones[2*i+1]) large = 2*i+1; if(2*i+2<heap_size && stones[large]<stones[2*i+2]) large = 2*i+2; if(large != i){ swap(stones[i], stones[large]); max_heapify(stones, large, heap_size); } } voidswap(int &a, int &b){ int temp; temp = a; a = b; b = temp; } };
Leetcode1047. Remove All Adjacent Duplicates In String
Given a string S of lowercase letters, a duplicate removal consists of choosing two adjacent and equal letters, and removing them.
We repeatedly make duplicate removals on S until we no longer can.
Return the final string after all such duplicate removals have been made. It is guaranteed the answer is unique.
Example 1:
1 2 3 4
Input: "abbaca" Output: "ca" Explanation: For example, in "abbaca" we could remove "bb" since the letters are adjacent and equal, and this is the only possible move. The result of this move is that the string is "aaca", of which only "aa" is possible, so the final string is "ca".
string removeDuplicates(string S){ string res = ""; for (char& c : S) if (res.size() && c == res.back()) res.pop_back(); else res.push_back(c); return res; }
1 2 3 4 5 6 7 8 9 10
classSolution { public: string removeDuplicates(string S){ string a; for (auto& c : S) if (a.size() && a.back() == c) a.pop_back(); else a.push_back(c); return a; } };
classSolution { public: string removeDuplicates(string S){ string res=""; int len = 0; int S_len = S.size(); for(int i=0;i<S_len;i++){ if( len>0 && res[len-1]==S[i]){ res.pop_back(); len--; } else{ res += S[i]; len++; } } return res; } };
Leetcode1048. Longest String Chain
Given a list of words, each word consists of English lowercase letters.
Let’s say word1 is a predecessor of word2 if and only if we can add exactly one letter anywhere in word1 to make it equal to word2. For example, “abc” is a predecessor of “abac”.
A word chain is a sequence of words [word_1, word_2, …, word_k] with k >= 1, where word_1 is a predecessor of word_2, word_2 is a predecessor of word_3, and so on.
Return the longest possible length of a word chain with words chosen from the given list of words.
Example 1:
1 2 3
Input: words = ["a","b","ba","bca","bda","bdca"] Output: 4 Explanation: One of the longest word chain is "a","ba","bda","bdca".
Example 2:
1 2
Input: words = ["xbc","pcxbcf","xb","cxbc","pcxbc"] Output: 5
Constraints:
1 <= words.length <= 1000
1 <= words[i].length <= 16
words[i] only consists of English lowercase letters.
classSolution { public: intlongestStrChain(vector<string>& words){ int n = words.size(), res = 1; sort(words.begin(), words.end(), [](string& a, string& b){ return a.size() < b.size(); }); unordered_map<string, int> dp; for (string word : words) { dp[word] = 1; for (int i = 0; i < word.size(); ++i) { string pre = word.substr(0, i) + word.substr(i + 1); if (dp.count(pre)) { dp[word] = max(dp[word], dp[pre] + 1); res = max(res, dp[word]); } } } return res; } };
Leetcode1049. Last Stone Weight II
You are given an array of integers stones where stones[i] is the weight of the ith stone.
We are playing a game with the stones. On each turn, we choose any two stones and smash them together. Suppose the stones have weights x and y with x <= y. The result of this smash is:
If x == y, both stones are destroyed, and If x != y, the stone of weight x is destroyed, and the stone of weight y has new weight y - x. At the end of the game, there is at most one stone left.
Return the smallest possible weight of the left stone. If there are no stones left, return 0.
Example 1:
1 2 3 4 5 6 7
Input: stones = [2,7,4,1,8,1] Output: 1 Explanation: We can combine 2 and 4 to get 2, so the array converts to [2,7,1,8,1] then, we can combine 7 and 8 to get 1, so the array converts to [2,1,1,1] then, we can combine 2 and 1 to get 1, so the array converts to [1,1,1] then, we can combine 1 and 1 to get 0, so the array converts to [1], then that's the optimal value.
classSolution { public: intlastStoneWeightII(vector<int>& stones){ vector<bool> dp(1501); dp[0] = true; int sum = 0; for (int stone : stones) { sum += stone; for (int i = min(1500, sum); i >= stone; --i) { dp[i] = dp[i] || dp[i - stone]; } } for (int i = sum / 2; i >= 0; --i) { if (dp[i]) return sum - 2 * i; } return0; } };
Leetcode1051. Height Checker
Students are asked to stand in non-decreasing order of heights for an annual photo.
Return the minimum number of students not standing in the right positions. (This is the number of students that must move in order for all students to be standing in non-decreasing order of height.)
Example 1:
1 2
Input: [1,1,4,2,1,3] Output: 3
Explanation: Students with heights 4, 3 and the last 1 are not standing in the right positions.
classSolution { public: /*int heightChecker(vector<int>& heights) { int res=0; for(int i=1;i<heights.size()-1;i++){ if(!(heights[i]>=heights[i-1] && heights[i]<=heights[i+1])) res++; } return res; } */ intheightChecker(vector<int>& h){ int res = 0 vector<int> s = h; sort(begin(s), end(s)); for (auto i = 0; i < h.size(); ++i) res += h[i] != s[i]; return res; } };
Leetcode1052. Grumpy Bookstore Owner
Today, the bookstore owner has a store open for customers.length minutes. Every minute, some number of customers (customers[i]) enter the store, and all those customers leave after the end of that minute.
On some minutes, the bookstore owner is grumpy. If the bookstore owner is grumpy on the i-th minute, grumpy[i] = 1, otherwise grumpy[i] = 0. When the bookstore owner is grumpy, the customers of that minute are not satisfied, otherwise they are satisfied.
The bookstore owner knows a secret technique to keep themselves not grumpy for X minutes straight, but can only use it once.
Return the maximum number of customers that can be satisfied throughout the day.
Example 1:
1 2 3 4
Input: customers = [1,0,1,2,1,1,7,5], grumpy = [0,1,0,1,0,1,0,1], X = 3 Output: 16 Explanation: The bookstore owner keeps themselves not grumpy for the last 3 minutes. The maximum number of customers that can be satisfied = 1 + 1 + 1 + 1 + 7 + 5 = 16.
Note:
1 <= X <= customers.length == grumpy.length <= 20000
0 <= customers[i] <= 1000
0 <= grumpy[i] <= 1
滑动窗口. 统计在大小为 X 的窗口中, 有多少顾客刚好处在店主脾气不好的时刻, 即grumpy[i] == 1。其中grumpy[i] == 0对应的顾客始终是满意的, 使用 base 来统计. 而对于那些grumpy[i] == 1的顾客, 只有在他们刚好在滑动窗口中, 才能满意, 用 new_satisfied 统计在滑动窗口中新满意的顾客, 在窗口滑动过程中使用 max_satisfied 来记录最大值. 最后返回 base + max_satisfied.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
classSolution { public: intmaxSatisfied(vector<int>& customers, vector<int>& grumpy, int minutes){ int res = 0, len = grumpy.size(); int sat = 0, new_sat = 0, max_sat = 0; for (int i = 0; i < len; i ++) { if (grumpy[i] == 0) sat += customers[i]; else new_sat += customers[i]; if (i >= minutes) new_sat -= (customers[i-minutes] * grumpy[i-minutes]); max_sat = max(max_sat, new_sat); } return sat + max_sat; } };
Leetcode1053. Previous Permutation With One Swap
Given an array of positive integers arr (not necessarily distinct), return the lexicographically largest permutation that is smaller than arr, that can be made with exactly one swap (A swap exchanges the positions of two numbers arr[i] and arr[j]). If it cannot be done, then return the same array.
这道题说在一个仓库,有一排条形码,这里用数字表示,现在让给数字重新排序,使得相邻的数字不相同,并且说了一定会有合理的答案。意思就是说最多的重复个数不会超过数组长度的一半,否则一定会有相邻的重复数字。那么来分析一下题目,既然是为了避免重复数字被排在相邻的位置,肯定是要优先关注出现次数多的数字,因为它们更有可能出现在相邻的位置。这道题是可以用贪婪算法来做的,每次取出出现次数最多的两个数字,将其先排列起来,然后再取下一对出现次数最多的两个数字,以此类推直至排完整个数组。这里为了快速知道出现次数最多的数字,可以使用优先队列来做,里面放一个 pair 对儿,由频率和数字组成,这样优先队列就可以根据频率由高到低来自动排序了。统计频率的话就使用一个 HashMap,然后将频率和数字组成的 pair 对儿加入优先队列。进行 while 循环,条件是队列中的 pair 对儿至少两个,这样才能每次取出两个,将其加入结果 res 中,然后其频率分别减1,只要没减到0,就都加回优先队列中。最后可能队列还有一个剩余,有的话将数字加入结果 res 中即可,参见代码如下:
classSolution { public: vector<int> rearrangeBarcodes(vector<int>& barcodes){ int n = barcodes.size(), pos = 0; vector<int> res(n); vector<pair<int, int>> vec; unordered_map<int, int> numCnt; for (int num : barcodes) ++numCnt[num]; for (auto &a : numCnt) { vec.push_back({a.second, a.first}); } sort(vec.rbegin(), vec.rend()); for (auto &a : vec) { for (int i = 0; i < a.first; ++i, pos += 2) { if (pos >= n) pos = 1; res[pos] = a.second; } } return res; } };
Leetcode1055. Shortest Way to Form String
From any string, we can form a subsequence of that string by deleting some number of characters (possibly no deletions).
Given two strings source and target, return the minimum number of subsequences of source such that their concatenation equals target. If the task is impossible, return -1.
Example 1:
1 2 3
Input: source = "abc", target = "abcbc" Output: 2 Explanation: The target "abcbc" can be formed by "abc" and "bc", which are subsequences of source "abc".
Example 2:
1 2 3
Input: source = "abc", target = "acdbc" Output: -1 Explanation: The target string cannot be constructed from the subsequences of source string due to the character "d" in target string.
Example 3:
1 2 3
Input: source = "xyz", target = "xzyxz" Output: 3 Explanation: The target string can be constructed as follows "xz" + "y" + "xz".
Constraints:
Both the source and target strings consist of only lowercase English letters from “a”-“z”.
The lengths of source and target string are between 1 and 1000.
classSolution { public: intshortestWay(string source, string target){ int res = 0, j = 0, m = source.size(), n = target.size(); while (j < n) { int pre = j; for (int i = 0; i < m; ++i) { if (j < n && source[i] == target[j]) ++j; } if (j == pre) return-1; ++res; } return res; } };
classSolution { public: intshortestWay(string source, string target){ int res = 1, pos = -1, n = target.size(); for (int i = 0; i < n; ++i) { if (source.find(target[i]) == -1) return-1; pos = source.find(target[i], pos + 1); if (pos == -1) { ++res; pos = source.find(target[i]); } } return res; } };
Leetcode1056. Confusing Number
Given a number N, return true if and only if it is a confusing number , which satisfies the following condition:
We can rotate digits by 180 degrees to form new digits. When 0, 1, 6, 8, 9 are rotated 180 degrees, they become 0, 1, 9, 8, 6 respectively. When 2, 3, 4, 5 and 7 are rotated 180 degrees, they become invalid. A confusing number is a number that when rotated 180 degrees becomes a different number with each digit valid.
Example 1:
1 2 3 4
Input: 6 Output: true Explanation: We get `9` after rotating `6`, `9` is a valid number and `9!=6`.
Example 2:
1 2 3 4
Input: 89 Output: true Explanation: We get `68` after rotating `89`, `86` is a valid number and `86!=89`.
Example 3:
1 2 3 4
Input: 11 Output: false Explanation: We get `11` after rotating `11`, `11` is a valid number but the value remains the same, thus `11` is not a confusing number.
Example 4:
1 2 3 4
Input: 25 Output: false Explanation: We get an invalid number after rotating `25`.
Note:
0 <= N <= 10^9
After the rotation we can ignore leading zeros, for example if after rotation we have 0008 then this number is considered as just 8.
这道题定义了一种迷惑数,将数字翻转 180 度,其中 0, 1, 8 旋转后保持不变,6变成9,9变成6,数字 2, 3, 4, 5, 和 7 旋转后变为非法数字。若能将某个数翻转后成为一个合法的新的数,就说这个数是迷惑数。这道题的难度并不大,就是考察的是遍历整数各个位上的数字,使用一个 while 循环,然后用 mod10 取出当前最低位上的数字,将不合法的数字放入一个 HashSet 中,这样直接在 HashSet 中查找一下当前数字是否存在,存在直接返回 false。不存在的话,则要进行翻转,因为只有6和9两个数字翻转后会得到不同的数字,所以单独判断一下,然后将当前数字拼到 num 的最低位即可,最终拼成的 num 就是原数字 N 的翻转,最后别忘了比较一下是否相同,参见代码如下:
解法一:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution { public: boolconfusingNumber(int N){ int num = 0, oldN = N; unordered_set<int> invalid{{2, 3, 4, 5, 7}}; while (N > 0) { int digit = N % 10; if (invalid.count(digit)) returnfalse; if (digit == 6) digit = 9; elseif (digit == 9) digit = 6; num = num * 10 + digit; N /= 10; } return num != oldN; } };
classSolution { public: boolconfusingNumber(int N){ unordered_map<int, int> m{{0, 0}, {1, 1}, {6, 9}, {8, 8}, {9, 6}}; long oldN = N, res = 0; while (N > 0) { if (!m.count(N % 10)) returnfalse; res = res * 10 + m[N % 10]; N /= 10; } return res != oldN; } };
下面来看一种双指针的解法,这里先用一个数组 rotate 来按位记录每个数字翻转后得到的数字,用 -1 来表示非法情况,然后将数字 N 转为字符串,用两个指针 left 和 right 分别指向开头和末尾。用 while 循环进行遍历,假如此时 left 和 right 中有任何一个指向的数字翻转后是非法,直接返回 false。然后看 left 指向的数字翻转后跟 right 指向的数字是否相同,若不同,则将 res 标记为 true,然后移动 left 和 right 指针,最终返回 res 即可,参见代码如下:
解法三:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
classSolution { public: boolconfusingNumber(int N){ bool res = false; vector<int> rotate{0, 1, -1, -1, -1, -1, 9, -1, 8, 6}; string str = to_string(N); int n = str.size(), left = 0, right = n - 1; while (left <= right) { if (rotate[str[left] - '0'] == -1 || rotate[str[right] - '0'] == -1) returnfalse; if (rotate[str[left] - '0'] != (str[right] - '0')) res = true; ++left; --right; } return res; } };
Leetcode1057. Campus Bikes
On a campus represented as a 2D grid, there are N workers and M bikes, with N <= M. Each worker and bike is a 2D coordinate on this grid.
Our goal is to assign a bike to each worker. Among the available bikes and workers, we choose the (worker, bike) pair with the shortest Manhattan distance between each other, and assign the bike to that worker. (If there are multiple (worker, bike) pairs with the same shortest Manhattan distance, we choose the pair with the smallest worker index; if there are multiple ways to do that, we choose the pair with the smallest bike index). We repeat this process until there are no available workers.
The Manhattan distance between two points p1 and p2 is Manhattan(p1, p2) = |p1.x - p2.x| + |p1.y - p2.y|.
Return a vector ans of length N, where ans[i] is the index (0-indexed) of the bike that the i-th worker is assigned to.
Example 1:
1 2 3 4
Input: workers = [[0,0],[2,1]], bikes = [[1,2],[3,3]] Output: [1,0] Explanation: Worker 1 grabs Bike 0 as they are closest (without ties), and Worker 0 is assigned Bike 1. So the output is [1, 0].
Example 2:
1 2 3 4
Input: workers = [[0,0],[1,1],[2,0]], bikes = [[1,0],[2,2],[2,1]] Output: [0,2,1] Explanation: Worker 0 grabs Bike 0 at first. Worker 1 and Worker 2 share the same distance to Bike 2, thus Worker 1 is assigned to Bike 2, and Worker 2 will take Bike 1. So the output is [0,2,1].
classSolution { public: vector<int> assignBikes(vector<vector<int>>& workers, vector<vector<int>>& bikes){ int m = workers.size(), n = bikes.size(); vector<int> assignedWorker(m, -1), assignedBike(n, -1); vector<vector<pair<int, int>>> buckets(2001); for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { int dist = abs(workers[i][0] - bikes[j][0]) + abs(workers[i][1] - bikes[j][1]); buckets[dist].push_back({i, j}); } } for (int dist = 0; dist <= 2000; ++dist) { for (int k = 0; k < buckets[dist].size(); ++k) { if (assignedWorker[buckets[dist][k].first] == -1 && assignedBike[buckets[dist][k].second] == -1) { assignedWorker[buckets[dist][k].first] = buckets[dist][k].second; assignedBike[buckets[dist][k].second] = buckets[dist][k].first; } } } return assignedWorker; } };
Leetcode1058. Minimize Rounding Error to Meet Target
Given an array of prices [p1,p2…,pn] and a target, round each price pi to Roundi(pi) so that the rounded array [Round1(p1),Round2(p2)…,Roundn(pn)] sums to the given target. Each operation Roundi(pi) could be either Floor(pi) or Ceil(pi).
Return the string “-1” if the rounded array is impossible to sum to target. Otherwise, return the smallest rounding error, which is defined as Σ |Roundi(pi) - (pi)| for i from 1 to n, as a string with three places after the decimal.
Example 1:
1 2 3 4
Input: prices = [“0.700”,”2.800”,”4.900”], target = 8 Output: “1.000” Explanation: Use Floor, Ceil and Ceil operations to get (0.7 - 0) + (3 - 2.8) + (5 - 4.9) = 0.7 + 0.2 + 0.1 = 1.0 .
Example 2:
1 2 3 4
Input: prices = [“1.500”,”2.500”,”3.500”], target = 10 Output: “-1” Explanation: It is impossible to meet the target.
Note:
1 <= prices.length <= 500.
Each string of prices prices[i] represents a real number which is between 0 and 1000 and has exactly 3 decimal places. target is between 0 and 1000000.
先对nums排序。然后开始遍历,计算nums相邻两个元素之间的数字数即nums[i] - pre - 1个,是否可以满足需要的k。如果能满足,那么直接找出要返回的数字pre+k。如果不能满足,把k去掉已能满足的数字nums[i] - pre - 1。最后如果所有的nums数字都已经用完,但是还不能满足k,则需要返回nums[nums.size() - 1] + k。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution { public: intmissingElement(vector<int>& nums, int k){ sort(nums.begin(), nums.end()); int pre = nums[0]; for (int i = 1; i < nums.size(); ++i) { if (k < nums[i] - pre) { return pre + k; } else { k -= nums[i] - pre - 1; } pre = nums[i]; } return pre + k; } };
classSolution { public: intfixedPoint(vector<int>& A){ int left = 0; int right = A.size() - 1; while (left + 1 < right) { int mid = left + (right - left) / 2; if (A[mid] >= mid) { right = mid; } else { left = mid; } } if (left == A[left]) { return left; } if (right == A[right]) { return right; } return-1; } };
Leetcode1065. Index Pairs of a String
Given a text string and words (a list of strings), return all index pairs [i, j] so that the substring text[i]…text[j] is in the list of words.
Example 1:
1 2
Input: text = “thestoryofleetcodeandme”, words = [“story”,”fleet”,”leetcode”] Output: [[3,7],[9,13],[10,17]]
Example 2:
1 2 3 4
Input: text = “ababa”, words = [“aba”,”ab”] Output: [[0,1],[0,2],[2,3],[2,4]] Explanation: Notice that matches can overlap, see “aba” is found in [0,2] and [2,4].
Note:
All strings contains only lowercase English letters.
It’s guaranteed that all strings in words are different.
1 <= text.length <= 100
1 <= words.length <= 20
1 <= words[i].length <= 50
Return the pairs [i,j] in sorted order (i.e. sort them by their first coordinate in case of ties sort them by their second coordinate).
classSolution { public: string gen(string str, int i){ string res; while (i--) { res += str; } return res; } string gcdOfStrings(string str1, string str2){ int l1 = str1.length(), l2 = str2.length(); int length = min(l1, l2); string res; for(int i = length; i > 0; i --) { if(l1 % i == 0 && l2 % i == 0) { int t1 = l1 / i; int t2 = l2 / i; string gcd = str1.substr(0, i); string s1 = gen(gcd, t1); string s2 = gen(gcd, t2); if ((s1 == str1) && (s2 == str2)) { res = gcd; break; } } } return res; } };
题目要求 X 能除尽 str1 且 X 能除尽 str2,且 X 为最长。那么可以理解为 str1 由 m 个 X 连接而成, str2 由 n 个 X 连接而成。由此可知 str1 + str2 由 m + n 个 X 拼接而成,而且 str1 + str2 与 str2 + str1 在值上是相等的。然后此题就转化为了求最大公约数。str1 和 str2 长度的最大公约数,就是所求 X 的长度。
classSolution { public: intmaxEqualRowsAfterFlips(vector<vector<int>>& matrix){ unordered_map<string, int> m; for (auto& mat : matrix) { int length = mat.size(); string str(length, ' '); if (mat[0] == 0){ for(int i = 0; i < length; i ++) { mat[i] ^= 1; str[i] = mat[i] == 1 ? '1': '0'; } } else { for(int i = 0; i < length; i ++) { str[i] = mat[i] == 1 ? '1' : '0'; } } m[str] ++; } int res = 0; for (auto it = m.begin(); it != m.end(); it ++) res = max(res, it->second); return res; } };
Leetcode1073. Adding Two Negabinary Numbers
Given two numbers arr1 and arr2 in base -2, return the result of adding them together.
Each number is given in array format: as an array of 0s and 1s, from most significant bit to least significant bit. For example, arr = [1,1,0,1] represents the number (-2)^3 + (-2)^2 + (-2)^0 = -3. A number arr in array, format is also guaranteed to have no leading zeros: either arr == [0] or arr[0] == 1.
Return the result of adding arr1 and arr2 in the same format: as an array of 0s and 1s with no leading zeros.
这道题说是有两个负二进制数是用数组来表示的,现在让返回它们相加后的结果,还是放在数组中来表示。这道题其实利用的方法跟那道很像,都是一位一位的处理的,直接加到结果 res 数组中的。这里使用两个指针i和j,分别指向数组 arr1 和 arr2 的末尾,然后用个变量 carry 表示进位,当i大于等于0时,carry 加上i指向的数字,并且i自减1,同理,当j大于等于0时,carry 加上j指向的数字,并且j自减1。由于数组中当每位上只能放一个数字,所以让 carry ‘与’上1,并加入到结果 res 数组后。然后需要再填充更高一位上的数字,对于二进制来说,直接右移1位即可,这里由于是负二进制,所以右移1位之后再取负。之后要移除所有的 leading zeros,因为这里高位是加到了 res 的后面,所以要去除末尾的零,使用个 while 去除。最后别忘了将 res 翻转一下返回即可,参见代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
classSolution { public: vector<int> addNegabinary(vector<int>& arr1, vector<int>& arr2){ vector<int> res; int carry = 0, i = (int)arr1.size() - 1, j = (int)arr2.size() - 1; while (i >= 0 || j >= 0 || carry) { if (i >= 0) carry += arr1[i--]; if (j >= 0) carry += arr2[j--]; res.push_back(carry & 1); carry = -(carry >> 1); } while (res.size() > 1 && res.back() == 0) res.pop_back(); reverse(res.begin(), res.end()); return res; } };
Leetcode1078. Occurrences After Bigram
Given words first and second, consider occurrences in some text of the form “first second third”, where second comes immediately after first, and third comes immediately after second.
For each such occurrence, add “third” to the answer, and return the answer.
Example 1:
1 2
Input: text = "alice is a good girl she is a good student", first = "a", second = "good" Output: ["girl","student"]
Example 2:
1 2
Input: text = "we will we will rock you", first = "we", second = "will" Output: ["we","rock"]
Note:
1 <= text.length <= 1000
text consists of space separated words, where each word consists of lowercase English letters.
1 <= first.length, second.length <= 10
first and second consist of lowercase English letters.
You have a set of tiles, where each tile has one letter tiles[i] printed on it. Return the number of possible non-empty sequences of letters you can make.
Example 1:
1 2 3
Input: "AAB" Output: 8 Explanation: The possible sequences are "A", "B", "AA", "AB", "BA", "AAB", "ABA", "BAA".
这道题实际上需要用单调栈的思路来做,首先需要统计每个字母出现的次数,这里可以使用一个大小为 128 的数组 cnt 来表示,还需要一个数组 visited 来记录某个字母是否出现过。先遍历一遍字符串,统计每个字母出现的次数到 cnt 中。再遍历一遍给定的字符串,对于遍历到的字母,在 cnt 数组中减去一个,然后看该字母是否已经在 visited 数组中出现过,是的话直接跳过。否则需要进行一个 while 循环,这里的操作实际上是为了确保得到的结果是字母顺序最小的,若当前字母小于结果 res 中的最后一个字母,且该最后的字母在 cnt 中还存在,说明之后还会遇到这个字母,则可以在 res 中先去掉这个字母,以保证字母顺序最小,并且 visited 数组中标记为0,表示未访问。这里是尽可能的将 res 打造成单调递增的,但如果后面没有这个字母了,就不能移除,所以说并不能保证一定是单调递增的,但可以保证得到的结果是字母顺序最小的。while 循环退出后,将该字母加到结果 res 后,并且 visited 标记为1。这里还有个小 trick,结果 res 在初始化给个0,这样就不用判空了,而且0是小于所有字母的,不会影响这个逻辑,最后返回的时候去掉首位0就行了,参见代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classSolution { public: string smallestSubsequence(string s){ string res = "0"; vector<int> cnt(128), visited(128); for (char c : s) ++cnt[c]; for (char c : s) { --cnt[c]; if (visited[c]) continue; while (c < res.back() && cnt[res.back()]) { visited[res.back()] = 0; res.pop_back(); } res += c; visited[c] = 1; } return res.substr(1); } };
Leetcode1089. Duplicate Zeros
Given a fixed length array arr of integers, duplicate each occurrence of zero, shifting the remaining elements to the right. Note that elements beyond the length of the original array are not written. Do the above modifications to the input array in place, do not return anything from your function.
Example 1:
1 2 3
Input: [1,0,2,3,0,4,5,0] Output: null Explanation: After calling your function, the input array is modified to: [1,0,0,2,3,0,0,4]
Example 2:
1 2 3
Input: [1,2,3] Output: null Explanation: After calling your function, the input array is modified to: [1,2,3]
classSolution { public: voidduplicateZeros(vector<int>& arr){ int n = arr.size(); int slow = 0, fast = 0; while(fast < n) { if(arr[slow] == 0) fast ++; fast ++; slow ++; } fast --; slow --; while(slow >= 0) { if(fast < n) arr[fast] = arr[slow]; if(arr[slow] == 0) arr[--fast] = arr[slow]; fast --; slow --; } } };
Leetcode1090. Largest Values From Labels
We have a set of items: the i-th item has value values[i] and label labels[i].
Then, we choose a subset S of these items, such that:
|S| <= num_wanted
For every label L, the number of items in S with label L is <= use_limit.
Return the largest possible sum of the subset S.
Example 1:
1 2 3
Input: values = [5,4,3,2,1], labels = [1,1,2,2,3], `num_wanted` = 3, use_limit = 1 Output: 9 Explanation: The subset chosen is the first, third, and fifth item.
Example 2:
1 2 3
Input: values = [5,4,3,2,1], labels = [1,3,3,3,2], `num_wanted` = 3, use_limit = 2 Output: 12 Explanation: The subset chosen is the first, second, and third item.
Example 3:
1 2 3
Input: values = [9,8,8,7,6], labels = [0,0,0,1,1], `num_wanted` = 3, use_limit = 1 Output: 16 Explanation: The subset chosen is the first and fourth item.
Example 4:
1 2 3
Input: values = [9,8,8,7,6], labels = [0,0,0,1,1], `num_wanted` = 3, use_limit = 2 Output: 24 Explanation: The subset chosen is the first, second, and fourth item.
classSolution { public: intshortestPathBinaryMatrix(vector<vector<int>>& grid){ if (grid[0][0] == 1) return-1; int res = 0, n = grid.size(); set<vector<int>> visited; visited.insert({0, 0}); queue<vector<int>> q; q.push({0, 0}); vector<vector<int>> dirs{{-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}}; while (!q.empty()) { ++res; for (int i = q.size(); i > 0; --i) { auto t = q.front(); q.pop(); if (t[0] == n - 1 && t[1] == n - 1) return res; for (auto dir : dirs) { int x = t[0] + dir[0], y = t[1] + dir[1]; if (x < 0 || x >= n || y < 0 || y >= n || grid[x][y] == 1 || visited.count({x, y})) continue; visited.insert({x, y}); q.push({x, y}); } } } return-1; } };
Leetcode1093. Statistics from a Large Sample
You are given a large sample of integers in the range [0, 255]. Since the sample is so large, it is represented by an array count where count[k] is the number of times that k appears in the sample.
Calculate the following statistics:
minimum: The minimum element in the sample.
maximum: The maximum element in the sample.
mean: The average of the sample, calculated as the total sum of all elements divided by the total number of elements.
median:
If the sample has an odd number of elements, then the median is the middle element once the sample is sorted.
If the sample has an even number of elements, then the median is the average of the two middle elements once the sample is sorted.
mode: The number that appears the most in the sample. It is guaranteed to be unique.
Return the statistics of the sample as an array of floating-point numbers [minimum, maximum, mean, median, mode]. Answers within 10-5 of the actual answer will be accepted.
Example 1:
1 2 3 4 5 6 7
Input: count = [0,1,3,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] Output: [1.00000,3.00000,2.37500,2.50000,3.00000] Explanation: The sample represented by count is [1,2,2,2,3,3,3,3]. The minimum and maximum are 1 and 3 respectively. The mean is (1+2+2+2+3+3+3+3) / 8 = 19 / 8 = 2.375. Since the size of the sample is even, the median is the average of the two middle elements 2 and 3, which is 2.5. The mode is 3 as it appears the most in the sample.
Example 2:
1 2 3 4 5 6 7
Input: count = [0,4,3,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] Output: [1.00000,4.00000,2.18182,2.00000,1.00000] Explanation: The sample represented by count is [1,1,1,1,2,2,2,3,3,4,4]. The minimum and maximum are 1 and 4 respectively. The mean is (1+1+1+1+2+2+2+3+3+4+4) / 11 = 24 / 11 = 2.18181818... (for display purposes, the output shows the rounded number 2.18182). Since the size of the sample is odd, the median is the middle element 2. The mode is 1 as it appears the most in the sample.
Constraints:
count.length == 256
0 <= count[i] <= 109
1 <= sum(count) <= 109
The mode of the sample that count represents is unique.
classSolution { public: vector<double> sampleStats(vector<int>& count){ double mn = 256, mx = 0, mean = 0, median = 0, sum = 0; int cnt = 0, mode = 0; for (int i = 0; i < count.size(); ++i) { if (count[i] == 0) continue; if (mn == 256) mn = i; mx = i; sum += (double)i * count[i]; cnt += count[i]; if (count[i] > count[mode]) mode = i; } mean = sum / cnt; int first = (cnt + 1) / 2, second = (cnt + 2) / 2, cur = 0; for (int i = 0; i < count.size(); ++i) { if (cur < first && cur + count[i] >= first) median += i / 2.0; if (cur < second && cur + count[i] >= second) median += i / 2.0; cur += count[i]; } return {mn, mx, sum / cnt, median, (double)mode}; } };
Leetcode1094. Car Pooling
You are driving a vehicle that has capacity empty seats initially available for passengers. The vehicle only drives east (ie. it cannot turn around and drive west.)
Given a list of trips, trip[i] = [num_passengers, start_location, end_location] contains information about the i-th trip: the number of passengers that must be picked up, and the locations to pick them up and drop them off. The locations are given as the number of kilometers due east from your vehicle’s initial location.
Return true if and only if it is possible to pick up and drop off all passengers for all the given trips.
HTTP 中包括许多方法,Get 和 Post 是 HTTP 中最常用的两个方法,基本上使用 HTTP 方法中有 99% 都是在使用 Get 方法和 Post 方法,所以有必要我们对这两个方法有更加深刻的认识。
get 方法一般用于请求,比如你在浏览器地址栏输入 www.cxuanblog.com 其实就是发送了一个 get 请求,它的主要特征是请求服务器返回资源,而 post 方法一般用于 表单的提交,相当于是把信息提交给服务器,等待服务器作出响应,get 相当于一个是 pull/拉的操作,而 post 相当于是一个 push/推的操作。get 方法是不安全的,因为你在发送请求的过程中,你的请求参数会拼在 URL 后面,从而导致容易被攻击者窃取,对你的信息造成破坏和伪造;/test/demo_form.asp?name1=value1&name2=value2而 post 方法是把参数放在请求体 body 中的,这对用户来说不可见。
1 2 3
POST /test/demo_form.asp HTTP/1.1 Host: w3schools.com name1=value1&name2=value2
get 请求的 URL 有长度限制,而 post 请求会把参数和值放在消息体中,对数据长度没有要求。
get 请求会被浏览器主动 cache,而 post 不会,除非手动设置。
get 请求在浏览器反复的 回退/前进 操作是无害的,而 post 操作会再次提交表单请求。
get 请求在发送过程中会产生一个 TCP 数据包;post 在发送过程中会产生两个 TCP 数据包。对于 get 方式的请求,浏览器会把 http header 和 data 一并发送出去,服务器响应 200(返回数据);而对于 post,浏览器先发送 header,服务器响应 100 continue,浏览器再发送 data,服务器响应 200 ok(返回数据)。
X-Frame-Options:HTTP 首部字段是可以自行扩展的。所以在 Web 服务器和浏览器的应用上,会出现各种非标准的首部字段。首部字段 X-Frame-Options 属于 HTTP 响应首部,用于控制网站内容在其他 Web 网站的 Frame 标签内的显示问题。其主要目的是为了防止点击劫持(clickjacking)攻击。
下面是一个响应头的汇总,基于 HTTP 1.1
地址栏输入 URL 发生了什么
首先,你需要在浏览器中的 URL 地址上,输入你想访问的地址。然后,浏览器会根据你输入的 URL 地址,去查找域名是否被本地 DNS 缓存,不同浏览器对 DNS 的设置不同,如果浏览器缓存了你想访问的 URL 地址,那就直接返回 ip。如果没有缓存你的 URL 地址,浏览器就会发起系统调用来查询本机 hosts 文件是否有配置 ip 地址,如果找到,直接返回。如果找不到,就向网络中发起一个 DNS 查询。
首先来看一下 DNS 是啥,互联网中识别主机的方式有两种,通过主机名和 IP 地址。我们人喜欢用名字的方式进行记忆,但是通信链路中的路由却喜欢定长、有层次结构的 IP 地址。所以就需要一种能够把主机名到 IP 地址的转换服务,这种服务就是由 DNS 提供的。DNS 的全称是 Domain Name System 域名系统。DNS 是一种由分层的 DNS 服务器实现的分布式数据库。DNS 运行在 UDP 上,使用 53 端口。
DNS 是一种分层数据库,它的主要层次结构如下
一般域名服务器的层次结构主要是以上三种,除此之外,还有另一类重要的 DNS 服务器,它是 本地 DNS 服务器(local DNS server)。严格来说,本地 DNS 服务器并不属于上述层次结构,但是本地 DNS 服务器又是至关重要的。每个 ISP(Internet Service Provider) 比如居民区的 ISP 或者一个机构的 ISP 都有一台本地 DNS 服务器。当主机和 ISP 进行连接时,该 ISP 会提供一台主机的 IP 地址,该主机会具有一台或多台其本地 DNS 服务器的 IP地址。通过访问网络连接,用户能够容易的确定 DNS 服务器的 IP地址。当主机发出 DNS 请求后,该请求被发往本地 DNS 服务器,它起着代理的作用,并将该请求转发到 DNS 服务器层次系统中。
首先,查询请求会先找到本地 DNS 服务器来查询是否包含 IP 地址,如果本地 DNS 无法查询到目标 IP 地址,就会向根域名服务器发起一个 DNS 查询。
classSolution { public: string freqAlphabets(string s){ string res = ""; for(int i = 0; i < s.length(); ) { char c = s[i]; if(i+2 < s.length() && s[i+2] == '#') { char cc = s[i+1]; int temp = (c - '0') * 10 + (cc - '0') - 1; res += ('a' + temp); i += 3; } else { char cc = 'a' + (c - '0' - 1); res += cc; i += 1; } } return res; } };
Leetcode1313. Decompress Run-Length Encoded List
We are given a list nums of integers representing a list compressed with run-length encoding.
Consider each adjacent pair of elements [freq, val] = [nums[2i], nums[2i+1]] (with i >= 0). For each such pair, there are freq elements with value val concatenated in a sublist. Concatenate all the sublists from left to right to generate the decompressed list.
Return the decompressed list.
Example 1:
1 2 3 4 5
Input: nums = [1,2,3,4] Output: [2,4,4,4] Explanation: The first pair [1,2] means we have freq = 1 and val = 2 so we generate the array [2]. The second pair [3,4] means we have freq = 3 and val = 4 so we generate [4,4,4]. At the end the concatenation [2] + [4,4,4] is [2,4,4,4].
classSolution { public: boolhave0(int nn){ while(nn) { int temp = nn % 10; if(temp == 0) returntrue; nn = nn / 10; } returnfalse; } vector<int> getNoZeroIntegers(int n){ for(int i = 1; i <= n/2; i ++) { if(!have0(i) && !have0(n-i)) return {i, n-i}; } return {}; } };
Leetcode1323. Maximum 69 Number
Given a positive integer num consisting only of digits 6 and 9. Return the maximum number you can get by changing at most one digit (6 becomes 9, and 9 becomes 6).
Example 1:
1 2 3 4 5 6 7 8
Input: num = 9669 Output: 9969 Explanation: Changing the first digit results in 6669. Changing the second digit results in 9969. Changing the third digit results in 9699. Changing the fourth digit results in 9666. The maximum number is 9969.
Example 2:
1 2 3
Input: num = 9996 Output: 9999 Explanation: Changing the last digit 6 to 9 results in the maximum number.
Example 3:
1 2 3
Input: num = 9999 Output: 9999 Explanation: It is better not to apply any change.
翻转一位数(6变9)找到最大的,只要找到从头到尾第一个6就行。
1 2 3 4 5 6 7 8 9 10 11 12 13
classSolution { public: intmaximum69Number(int num){ string numm = to_string(num); for(int i =0; i < numm.size(); i ++) { if(numm[i] == '6'){ numm[i] = '9'; returnstoi(numm); } } return num; } };
Leetcode1331. Rank Transform of an Array
Given an array of integers arr, replace each element with its rank. The rank represents how large the element is. The rank has the following rules:
Rank is an integer starting from 1. The larger the element, the larger the rank. If two elements are equal, their rank must be the same. Rank should be as small as possible.
Example 1:
1 2 3
Input: arr = [40,10,20,30] Output: [4,1,2,3] Explanation: 40 is the largest element. 10 is the smallest. 20 is the second smallest. 30 is the third smallest.
把一个数组中的数字用排序后这个数字的rank来替换,注意没有跨越rank的那种情况。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
classSolution { public: vector<int> arrayRankTransform(vector<int>& arr){ map<int, int> mp; vector<int> rr(arr); sort(rr.begin(), rr.end()); int rank = 1; for(int i = 0; i < rr.size(); i ++) { if(mp[rr[i]] == 0) mp[rr[i]] = rank ++; } for(int i = 0; i < arr.size(); i ++) { arr[i] = mp[arr[i]]; } return arr; } };
Leetcode1332. Remove Palindromic Subsequences
Given a string s consisting only of letters ‘a’ and ‘b’. In a single step you can remove one palindromic subsequence from s.
Return the minimum number of steps to make the given string empty.
A string is a subsequence of a given string, if it is generated by deleting some characters of a given string without changing its order.
A string is called palindrome if is one that reads the same backward as well as forward.
Example 1:
1 2 3
Input: s = "ababa" Output: 1 Explanation: String is already palindrome
Example 2:
1 2 3 4
Input: s = "abb" Output: 2 Explanation: "abb" -> "bb" -> "". Remove palindromic subsequence "a" then "bb".
Example 3:
1 2 3 4
Input: s = "baabb" Output: 2 Explanation: "baabb" -> "b" -> "". Remove palindromic subsequence "baab" then "b".
Example 4:
1 2
Input: s = "" Output: 0
由于只有 a 和 b 两个字符。其实最多的消除次数就是 2。因为我们无论如何都可以先消除全部的 1 再消除全部的 2(先消除 2 也一样),这样只需要两次即可完成。 我们再看一下题目给的一次消除的情况,题目给的例子是“ababa”,我们发现其实它本身就是一个回文串,所以才可以一次全部消除。那么思路就有了:
如果 s 是回文,则我们需要一次消除;否则需要两次,一定要注意特殊情况, 对于空字符串,我们需要 0 次
Given a m * n matrix mat of ones (representing soldiers) and zeros (representing civilians), return the indexes of the k weakest rows in the matrix ordered from the weakest to the strongest.
A row i is weaker than row j, if the number of soldiers in row i is less than the number of soldiers in row j, or they have the same number of soldiers but i is less than j. Soldiers are always stand in the frontier of a row, that is, always ones may appear first and then zeros.
Example 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Input: mat = [[1,1,0,0,0], [1,1,1,1,0], [1,0,0,0,0], [1,1,0,0,0], [1,1,1,1,1]], k = 3 Output: [2,0,3] Explanation: The number of soldiers for each row is: row 0 -> 2 row 1 -> 4 row 2 -> 1 row 3 -> 2 row 4 -> 5 Rows ordered from the weakest to the strongest are [2,0,3,1,4]
Example 2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Input: mat = [[1,0,0,0], [1,1,1,1], [1,0,0,0], [1,0,0,0]], k = 2 Output: [0,2] Explanation: The number of soldiers for each row is: row 0 -> 1 row 1 -> 4 row 2 -> 1 row 3 -> 1 Rows ordered from the weakest to the strongest are [0,2,3,1]
classSolution { public: vector<int> kWeakestRows(vector<vector<int>>& mat, int k){ vector<int> weak; for(int i = 0; i < mat.size(); i ++) { weak.push_back(0); int count = 0; for(int j = 0; j < mat[i].size(); j ++) { count += mat[i][j]; } weak[i] = count; } map<int, vector<int>> mp; for(int i = 0; i < mat.size(); i ++) { mp[weak[i]].push_back(i); } sort(weak.begin(), weak.end()); vector<int> res; int kk = 0; for(auto i = mp.begin(); i != mp.end() ; i ++) { for(int ii = 0; ii < (i->second).size(); ii ++) { res.push_back((i->second)[ii]); kk ++; if(kk == k) break; } if(kk == k) break; } return res; } };
Leetcode1340. Jump Game V
Given an array of integers arr and an integer d. In one step you can jump from index i to index:
i + x where: i + x < arr.length and 0 < x <= d.
i - x where: i - x >= 0 and 0 < x <= d.
In addition, you can only jump from index i to index j if arr[i] > arr[j] and arr[i] > arr[k] for all indices k between i and j (More formally min(i, j) < k < max(i, j)).
You can choose any index of the array and start jumping. Return the maximum number of indices you can visit.
Notice that you can not jump outside of the array at any time.
Example 1:
1 2 3 4 5
Input: arr = [6,4,14,6,8,13,9,7,10,6,12], d = 2 Output: 4 Explanation: You can start at index 10. You can jump 10 --> 8 --> 6 --> 7 as shown. Note that if you start at index 6 you can only jump to index 7. You cannot jump to index 5 because 13 > 9. You cannot jump to index 4 because index 5 is between index 4 and 6 and 13 > 9. Similarly You cannot jump from index 3 to index 2 or index 1.
Example 2:
1 2 3
Input: arr = [3,3,3,3,3], d = 3 Output: 1 Explanation: You can start at any index. You always cannot jump to any index.
Example 3:
1 2 3
Input: arr = [7,6,5,4,3,2,1], d = 1 Output: 7 Explanation: Start at index 0. You can visit all the indicies.
Constraints:
1 <= arr.length <= 1000
1 <= arr[i] <= 105
1 <= d <= arr.length
给你一个整数数组 arr 和一个整数 d 。每一步你可以从下标 i 跳到:
i + x ,其中 i + x < arr.length 且 0 < x <= d 。
i - x ,其中 i - x >= 0 且 0 < x <= d 。
除此以外,你从下标 i 跳到下标 j 需要满足:arr[i] > arr[j] 且 arr[i] > arr[k] ,其中下标 k 是所有 i 到 j 之间的数字(更正式的,min(i, j) < k < max(i, j))。
classSolution { public: vector<vector<int>> g; vector<int> dp; intdfs(int u){ if (dp[u] != -1) return dp[u]; dp[u] = 0; for (int v : g[u]) { int dist = dfs(v); // f[v] dp[u] = max(dp[u], dist); // 取最大的f[v] } dp[u] ++; // 这个++表示u到v的这条边 return dp[u]; } intmaxJumps(vector<int>& arr, int d){ int n = arr.size(); g.assign(n, vector<int>()); for (int i = 0; i < n; i ++) { // 在两个方向上,构图 for (int j = 1; j <= d && i - j >= 0 && arr[i-j] < arr[i]; j ++) // 最远不能超过d,高度小过a[i],不能跑出去边界 g[i].push_back(i - j); for (int j = 1; j <= d && i + j < n && arr[i+j] < arr[i]; j ++) // 最远不能超过d,高度小过a[i],不能跑出去边界 g[i].push_back(i + j); } dp.assign(n, -1); // 从一个点出发能走的最长路径 for (int i = 0; i < n; i ++) dfs(i);
int res = -1; for (int i = 0; i < n; i ++) res = max(res, dp[i]); return res; } };
Leetcode1346. Check If N and Its Double Exist
Given an array arr of integers, check if there exists two integers N and M such that N is the double of M ( i.e. N = 2 * M).
More formally check if there exists two indices i and j such that :
i != j
0 <= i, j < arr.length
arr[i] == 2 * arr[j]
Example 1:
1 2 3
Input: arr = [10,2,5,3] Output: true Explanation: N = 10 is the double of M = 5,that is, 10 = 2 * 5.
Example 2:
1 2 3
Input: arr = [7,1,14,11] Output: true Explanation: N = 14 is the double of M = 7,that is, 14 = 2 * 7.
Example 3:
1 2 3
Input: arr = [3,1,7,11] Output: false Explanation: In this case does not exist N and M, such that N = 2 * M.
注意0的问题,只有有两个0的时候返回true
1 2 3 4 5 6 7 8 9 10 11 12 13
classSolution { public: boolcheckIfExist(vector<int>& arr){ map<int, int> mp; for(int i = 0; i < arr.size(); i ++) mp[arr[i]] ++; for(int i = 0; i < arr.size(); i ++) { if(mp[arr[i]*2] && arr[i] != 0 || arr[i] == 0 && mp[arr[i]] > 1 ) returntrue; } returnfalse; } };
Leetcode1349. Maximum Students Taking Exam
Given a m * n matrix seats that represent seats distributions in a classroom. If a seat is broken, it is denoted by ‘#’ character otherwise it is denoted by a ‘.’ character.
Students can see the answers of those sitting next to the left, right, upper left and upper right, but he cannot see the answers of the student sitting directly in front or behind him. Return the maximum number of students that can take the exam together without any cheating being possible..
Students must be placed in seats in good condition.
Example 1:
1 2 3 4 5
Input: seats = [["#",".","#","#",".","#"], [".","#","#","#","#","."], ["#",".","#","#",".","#"]] Output: 4 Explanation: Teacher can place 4 students in available seats so they don't cheat on the exam.
Example 2:
1 2 3 4 5 6 7
Input: seats = [[".","#"], ["#","#"], ["#","."], ["#","#"], [".","#"]] Output: 3 Explanation: Place all students in available seats.
Example 3:
1 2 3 4 5 6 7
Input: seats = [["#",".",".",".","#"], [".","#",".","#","."], [".",".","#",".","."], [".","#",".","#","."], ["#",".",".",".","#"]] Output: 10 Explanation: Place students in available seats in column 1, 3 and 5.
classSolution { public: boolcheck2(int s, int ss, int m){ for (int k = 0; k < m; k ++) { int b = (s >> k) & 1; if (!b) continue; int bss0 = 0, bss2 = 0; if (k) bss0 = (ss >> (k-1)) & 1; if (k != m-1) bss2 = (ss >> (k+1)) & 1; if (bss0 || bss2) returnfalse; } returntrue; } boolcheck(int s, const vector<char>& line, int m){ int preb = 0; for (int k = 0; k < m; k ++) { int b = (s >> k) & 1; if (b && line[k] == '#') returnfalse; if (preb && b) returnfalse; preb = b; } returntrue; } intmaxStudents(vector<vector<char>>& seats){ int n = seats.size(), m = seats[0].size(); int maxseats = 1 << m; vector<int> y(maxseats, 0); vector<int> x(maxseats, 0); vector<bool> oky(maxseats, true); vector<bool> okx(maxseats, true); for (int i = 0; i < n; i ++) { x.assign(maxseats, 0); okx.assign(maxseats, false); for (int s = 0; s < maxseats; s ++) { okx[s] = check(s, seats[i], m); if (!okx[s]) continue; int cnt = 0; for (int k = 0; k < m; k ++) cnt += ( s >> k) & 1; for (int ss = 0; ss < maxseats; ss ++) if (oky[ss]) { if (!check2(s, ss, m)) continue; x[s] = max(x[s], y[ss] + cnt); } } swap(x, y); swap(okx, oky); } int maxv = 0; for (int v : y) maxv = max(maxv, v); return maxv; } };
Leetcode1351. Count Negative Numbers in a Sorted Matrix
Given a m * n matrix grid which is sorted in non-increasing order both row-wise and column-wise. Return the number of negative numbers in grid.
Example 1:
1 2 3
Input: grid = [[4,3,2,-1],[3,2,1,-1],[1,1,-1,-2],[-1,-1,-2,-3]] Output: 8 Explanation: There are 8 negatives number in the matrix.
统计一个矩阵中有多少个负数?有毛病,这么简单。
1 2 3 4 5 6 7 8 9 10 11
classSolution { public: intcountNegatives(vector<vector<int>>& grid){ int res = 0; for(int i = 0; i < grid.size(); i ++) for(int j = 0; j < grid[0].size(); j ++) if(grid[i][j] < 0) res ++; return res; } };
Leetcode1356. Sort Integers by The Number of 1 Bits
Given an integer array arr. You have to sort the integers in the array in ascending order by the number of 1’s in their binary representation and in case of two or more integers have the same number of 1’s you have to sort them in ascending order.
Return the sorted array.
Example 1:
1 2 3 4 5 6 7
Input: arr = [0,1,2,3,4,5,6,7,8] Output: [0,1,2,4,8,3,5,6,7] Explantion: [0] is the only integer with 0 bits. [1,2,4,8] all have 1 bit. [3,5,6] have 2 bits. [7] has 3 bits. The sorted array by bits is [0,1,2,4,8,3,5,6,7]
Example 2:
1 2 3
Input: arr = [1024,512,256,128,64,32,16,8,4,2,1] Output: [1,2,4,8,16,32,64,128,256,512,1024] Explantion: All integers have 1 bit in the binary representation, you should just sort them in ascending order.
classSolution { public: staticintbitnum(int a){ int res = 0; while(a) { res += a & 1; a = a >> 1; } return res; } staticboolcmp(int a, int b){ if(bitnum(a) < bitnum(b)) returntrue; elseif(bitnum(a) == bitnum(b)) return a < b; else returnfalse; } vector<int> sortByBits(vector<int>& arr){ sort(arr.begin(), arr.end(), cmp); return arr; } };
Leetcode1360. Number of Days Between Two Dates
Write a program to count the number of days between two dates. The two dates are given as strings, their format is YYYY-MM-DD as shown in the examples.
Leetcode1365. How Many Numbers Are Smaller Than the Current Number
Given the array nums, for each nums[i] find out how many numbers in the array are smaller than it. That is, for each nums[i] you have to count the number of valid j’s such that j != i and nums[j] < nums[i].
Return the answer in an array.
Example 1:
1 2 3 4 5 6 7 8
Input: nums = [8,1,2,2,3] Output: [4,0,1,1,3] Explanation: For nums[0]=8 there exist four smaller numbers than it (1, 2, 2 and 3). For nums[1]=1 does not exist any smaller number than it. For nums[2]=2 there exist one smaller number than it (1). For nums[3]=2 there exist one smaller number than it (1). For nums[4]=3 there exist three smaller numbers than it (1, 2 and 2).
classSolution { public: vector<int> smallerNumbersThanCurrent(vector<int>& nums){ vector<int> res; map<int, int> mp; for(int i = 0; i < nums.size(); i ++) { mp[nums[i]] ++; } int presum = 0; for(auto a = mp.begin(); a != mp.end(); a ++) { int sec = a->second; mp[a->first] = presum; presum = presum + sec; } for(int i = 0; i < nums.size(); i ++){ res.push_back(mp[nums[i]]); } return res; } };
Leetcode1370. Increasing Decreasing String
Given a string s. You should re-order the string using the following algorithm:
Pick the smallest character from s and append it to the result.
Pick the smallest character from s which is greater than the last appended character to the result and append it.
Repeat step 2 until you cannot pick more characters.
Pick the largest character from s and append it to the result.
Pick the largest character from s which is smaller than the last appended character to the result and append it.
Repeat step 5 until you cannot pick more characters.
Repeat the steps from 1 to 6 until you pick all characters from s.
In each step, If the smallest or the largest character appears more than once you can choose any occurrence and append it to the result.
Return the result string after sorting s with this algorithm.
Example 1:
1 2 3 4 5 6 7
Input: s = "aaaabbbbcccc" Output: "abccbaabccba" Explanation: After steps 1, 2 and 3 of the first iteration, result = "abc" After steps 4, 5 and 6 of the first iteration, result = "abccba" First iteration is done. Now s = "aabbcc" and we go back to step 1 After steps 1, 2 and 3 of the second iteration, result = "abccbaabc" After steps 4, 5 and 6 of the second iteration, result = "abccbaabccba"
classSolution { public: string sortString(string s){ string res; vector<int> ma(26, 0); int i = 0, len = s.length(); for(int i = 0; i < len; i ++) ma[s[i] - 'a'] ++; int count = 0; while(count < len) { for(int i = 0; i < 26; i ++) if(ma[i]) { res += ('a' + i); ma[i] --; count ++; } for(int i = 25; i >= 0; i --) if(ma[i]) { res += ('a' + i); ma[i] --; count ++; } } return res; } };
Leetcode1374. Generate a String With Characters That Have Odd Counts
Given an integer n, return a string with n characters such that each character in such string occurs an odd number of times. The returned string must contain only lowercase English letters. If there are multiples valid strings, return any of them.
Example 1:
1 2 3
Input: n = 4 Output: "pppz" Explanation: "pppz" is a valid string since the character 'p' occurs three times and the character 'z' occurs once. Note that there are many other valid strings such as "ohhh" and "love".
Example 2:
1 2 3
Input: n = 2 Output: "xy" Explanation: "xy" is a valid string since the characters 'x' and 'y' occur once. Note that there are many other valid strings such as "ag" and "ur".
返回一个字符串,每个字母都只出现过奇数次。神经病题,要处理奇数和偶数的不同情况。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution { public: string generateTheString(int n){ string res; if(n % 2 == 0) { for(int i = 0; i < n-1; i ++) res += 'a'; res += 'b'; } if(n % 2 == 1) { for(int i = 0; i < n; i ++) res += 'a'; } return res; } };
Leetcode1380. Lucky Numbers in a Matrix
Given a m * n matrix of distinct numbers, return all lucky numbers in the matrix in any order. A lucky number is an element of the matrix such that it is the minimum element in its row and maximum in its column.
Example 1:
1 2 3
Input: matrix = [[3,7,8],[9,11,13],[15,16,17]] Output: [15] Explanation: 15 is the only lucky number since it is the minimum in its row and the maximum in its column
Example 2:
1 2 3
Input: matrix = [[1,10,4,2],[9,3,8,7],[15,16,17,12]] Output: [12] Explanation: 12 is the only lucky number since it is the minimum in its row and the maximum in its column.
classSolution { public: vector<int> luckyNumbers(vector<vector<int>>& matrix){ vector<int> res; int row = matrix.size(), col = matrix[0].size(); for(int i = 0; i < row; i ++) { int j = 0, minn = 999999, minn_j = -1; for(; j < col; j ++) { if(minn > matrix[i][j]) { minn = matrix[i][j]; minn_j = j; } } int ii; for(ii = 0; ii < row; ii ++) if(matrix[ii][minn_j] > minn) break; if(ii == row) res.push_back(minn); } return res; } };
Leetcode1385. Find the Distance Value Between Two Arrays
Given two integer arrays arr1 and arr2, and the integer d, return the distance value between the two arrays. The distance value is defined as the number of elements arr1[i] such that there is not any element arr2[j] where |arr1[i]-arr2[j]| <= d.
Example 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
Input: arr1 = [4,5,8], arr2 = [10,9,1,8], d = 2 Output: 2 Explanation: For arr1[0]=4 we have: |4-10|=6 > d=2 |4-9|=5 > d=2 |4-1|=3 > d=2 |4-8|=4 > d=2 For arr1[1]=5 we have: |5-10|=5 > d=2 |5-9|=4 > d=2 |5-1|=4 > d=2 |5-8|=3 > d=2 For arr1[2]=8 we have: |8-10|=2 <= d=2 |8-9|=1 <= d=2 |8-1|=7 > d=2 |8-8|=0 <= d=2
计算一行中没有差的绝对值大于d的行数。「距离值」 定义为符合此描述的元素数目:对于元素 arr1[i] ,不存在任何元素 arr2[j] 满足 |arr1[i]-arr2[j]| <= d 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution { public: intfindTheDistanceValue(vector<int>& arr1, vector<int>& arr2, int d){ int res = 0; for(int i = 0; i < arr1.size(); i ++) { int j; for(j = 0; j < arr2.size(); j ++) { if(abs(arr1[i] - arr2[j]) <= d) break; } if(j == arr2.size()) res ++; } return res; } };
Leetcode1389. Create Target Array in the Given Order
Given two arrays of integers nums and index. Your task is to create target array under the following rules:
Initially target array is empty.
From left to right read nums[i] and index[i], insert at index index[i] the value nums[i] in target array.
Repeat the previous step until there are no elements to read in nums and index.
Return the target array.
It is guaranteed that the insertion operations will be valid.
voidmove(vector<int>& nums, int i){ int ii; for(ii = i + 1; ii < nums.size() && nums[ii] != -1; ii ++); for(int k = ii; k > i; k --) { nums[k] = nums[k-1]; } } vector<int> createTargetArray(vector<int>& nums, vector<int>& index){ vector<int> res(nums.size(), -1); for(int i = 0; i < nums.size(); i ++) { if(res[index[i]] == -1) res[index[i]] = nums[i]; else { move(res, index[i]); res[index[i]] = nums[i]; } } return res; } };
Leetcode1394. Find Lucky Integer in an Array
Given an array of integers arr, a lucky integer is an integer which has a frequency in the array equal to its value. Return a lucky integer in the array. If there are multiple lucky integers return the largest of them. If there is no lucky integer return -1.
Example 1:
1 2 3
Input: arr = [2,2,3,4] Output: 2 Explanation: The only lucky number in the array is 2 because frequency[2] == 2.
Example 2:
1 2 3
Input: arr = [1,2,2,3,3,3] Output: 3 Explanation: 1, 2 and 3 are all lucky numbers, return the largest of them.
classSolution { public: intfindLucky(vector<int>& arr){ sort(arr.begin(), arr.end()); int prev = arr[0], count = 1, res = -1; for(int i = 1; i < arr.size(); i ++) { if(prev != arr[i]) { if(count == prev) res = prev; prev = arr[i]; count = 1; } else { count ++; } } if(count == prev) res = prev; return res; } };
Leetcode1399. Count Largest Group
Given an integer n. Each number from 1 to n is grouped according to the sum of its digits. Return how many groups have the largest size.
Example 1:
1 2 3 4
Input: n = 13 Output: 4 Explanation: There are 9 groups in total, they are grouped according sum of its digits of numbers from 1 to 13: [1,10], [2,11], [3,12], [4,13], [5], [6], [7], [8], [9]. There are 4 groups with largest size.
CPU访问内存是用段地址+偏移地址来实现的,由于在实模式之下,段地址需要乘以16后才能与偏移地址相加,求出的和便是物理地址,CPU便拿此地址直接用了。在接电的一瞬间,CPU的cs:ip寄存器被强制初始化为0xF000:0xFFF0。由于开机的时候处于实模式,在实模式下的段基址要乘以16,也就是左移4位,于是0xF000:0xFFF0的等效地址将是0xFFFF0,此地址便是BIOS的入口地址。物理地址0xFFFF0处应该是指令,否则会出错,里面有条指令jmp far f000:e05b,这是条跳转指令,也就是证明了在内存物理地址0xFFFF0处的内容是一条跳转指令。
8086CPU要求物理地址0x0~0x3FF存放中断向量表,所以此处不能动了;按 DOS 1.0 要求的最小内存32KB来说,MBR希望给人家尽可能多的预留空间,所以MBR只能放在32KB的末尾;MBR本身也是程序,是程序就要用到栈,估计1KB内存够用了。结合以上三点,选择32KB中的最后1KB最为合适,32KB换算为十六进制为0x8000,减去1KB(0x400)的话,等于0x7c00。这就是倍受质疑的0x7c00 的由来。
对于受访者为数据段(段描述符中 type 字段中未有X 可执行属性)来说:只有访问者的权限大于等于该DPL 表示的最低权限才能够继续访问,否则连这个门槛都迈不过去。对于受访者为代码段(段描述符中 type 字段中含有X 可执行属性)来说:只有访问者的权限等于该DPL 表示的最低权限才能够继续访问,CPU 没有理由先自降等级后再去做某事。
操作系统为每个进程提供了一个PCB,Process Control Block,即程序控制块,用它来记录与此进程相关的信息,比如进程状态、PID、优先级等。每个进程都有自己的PCB,所有PCB 放到一张表格中维护,这就是进程表,PCB 又可称为进程表项。“寄存器映像”用来保存进程的“现场”,进程在处理器上运行时,所有寄存器的值都将保存到此处。
汇编代码在输出部分,"g" (thread->self_kstack)使thread->self_kstack的值作为输入,采用通用约束g,即内存或寄存器都可以。在汇编语句部分, movl %0, %%esp,也就是使thread->self_kstack的值作为栈顶,此时thread->self_kstack指向线程栈的最低处,这是我们在函数thread_create中设定的。接下来的这连续4 个弹栈操作:pop %%ebp; pop %%ebx; pop %%edi; pop %%esi使之前初始化的0 弹入到相应寄存器中。
Linux 提供了称为文件结构的数据结构,专门用于记录与文件操作相关的信息,每次打开一个文件就会产生一个文件结构,多次打开该文件就为该文件生成多个文件结构,各自文件操作的偏移量分别记录在不同的文件结构中,从而实现了即使同一个文件被同时多次打开,各自操作的偏移量也互不影响的灵活性。Linux 把所有的“文件结构”组织到一起形成数组统一管理,该数组称为文件表。
/* init 进程 */ voidinit(void){ uint32_t ret_pid = fork(); if(ret_pid) { printf("i am father, my pid is %d, child pid is %d\n", getpid(), ret_pid); } else { printf("i am child, my pid is %d, ret pid is %d\n", getpid(), ret_pid); } while(1); }
为了解决这一问题,Raft提出了两阶段的成员变更方法。集群先从旧成员配置Cold切换到一个过渡成员配置,称为共同一致(joint consensus),共同一致是旧成员配置Cold和新成员配置Cnew的组合Cold U Cnew,一旦共同一致Cold U Cnew被提交,系统再切换到新成员配置Cnew。
完美的静态分析满足sound和complete的。Sound > Truth > Complete,Truth是说所有可能的行为,Sound说的是包含Truth且有其他的,Complete只有Truth中所有可能行为的一部分,Complete中爆出来的一定是Truth中的,而Sound中爆出来的不一定是Truth中的。
transfer function:正常的分析是按照程序执行的顺序分析。语句s对应的transfer function用fs来表示,则OUT[s] = fs(IN[s]),这句话是说,输入是执行s之前的value=IN[s],转化为s执行完之后状态OUT[s]。另一种是反向分析,逆向程序执行的顺序,则IN[s] = fs(OUT[s])。
控制流的约束(control flow’s constraints):一共是n条语句,在一个代码块中的控制流,IN[s(s+1)] = OUT[s(i)], for all i = 1, 2, ..., n-1,每一个语句的IN都是上一个语句的OUT。代码块的关系:IN[B]=IN[s1] OUT[B]=OUT[sn]。
一个基本块的transfer function,是其中所有语句的transfer function,即OUT[B]=fb(IN[B]), fb=fsn*...*fs2*fs1,IN[B]=∩ (P: a predecessor of B) OUT[P]
D: v = x op y这个语句生成v的一个definition,然后‘kills’其他所有对v的定义,但是保留了对其他变量的定义。transfer function为OUT[B]=(gen B)∪(IN[B]-kill(B)),去掉其他所有定义这个变量的语句。
control flow:IN[B]=∪ (P: a predecessor of B) OUT[P],就是B所有的前驱P的OUT的并,一条结果都不放过,都考虑成B的IN。
定义可达性分析算法:
1 2 3 4 5 6 7 8 9 10 11
INPUT: CFG(kill(B) and gen(B) computed for each basic block B) OUTPUT: IN[B] and OUT[B] for each basic block B METHOD: OUT[entry] = Φ for (each basic block B\entry) OUT[B] = Φ while(changes to any OUT occur) for(each basic block B\entry) { IN[B] = ∪ (P: a predecessor of B) OUT[P] OUT[B] = gen(B) ∪ (IN[B] - kill(B)) }
INPUT: CFG(def(B) and use(B) computed for each basic block B) OUTPUT: IN[B] and OUT[B] for each basic block B METHOD: IN[exit] = Φ for (each basic block B\entry) IN[B] = Φ while(changes to any IN occur) for(each basic block B\exit) { OUT[B] = ∪ (P: a successor of B) IN[P] IN[B] = use(B) ∪ (OUT[B] - def(B)) }
对一个程序进行分析,跟上边的分析类似,只是是从下向上的分析。
Available Expressions Analysis可用表达式分析
一个表达式x op y,如果所有路径从入口到p都一定要计算表达式x op y,且在计算x op y之后没有x和y的重定义,则称表达式x op y在点p是活的。
这个定义也说明了在程序p中,可以用x op y的结果替换掉这个表达式。
这个可以用于检测全局的通用表达式
抽象:表达式可以用bit vector来表示。
对于a = x op y,使用forward分析方法,它的IN={a+b},它的OUT中应该加上x op y,因为x op y是刚执行的,被看成是gen;然后从IN中删掉所有涉及a的语句,这被看成是kill。所以,OUT[B]=gen(B)∪(IN[B]-kill(B)),IN[B]=∩(P a predecessor of B)OUT[P]。这里使用了交集,因为所有从入口到p点的路径都需要通过x op y这个函数。
INPUT: CFG(kill(B) and gen(B) computed for each basic block B) OUTPUT: IN[B] and OUT[B] for each basic block B METHOD: OUT[entry] = Φ for (each basic block B\entry) OUT[B] = Φ while(changes to any OUT occur) for(each basic block B\entry) { IN[B] = ∩ (P: a predecessor of B) OUT[P] OUT[B] = gen(B) ∪ (IN[B] - kill(B)) }
May Analyses是一个bottom,代表一个不安全的结果,算是一个下界;另外有一个上界,是安全但是不完全/没用的结果。这里中间有一个Truth,将safe和unsafe隔开。如何知道分析一定是safe的?这是由单调性决定的。May Analyses从底部一直向上走,我们向上走先接触到的是最小不动点。从最底部走到最顶部,是从精度最高走到精度最低的。所以May Analyses一般都首先初始化为空。
MOP就是枚举从Entry到Si所有的Path,然后把三条路径的FP结果join/meet起来,公式是:MOP[Si] = ⊔/⊓ FP(OUT[Entry]), A path P from Entry to Si,所有path应用transfer function之后进行meet/join,找到确界。有一些path是不可能走到的,所以这是不精确的。
INPUT: CFG(kill(B) and gen(B) computed for each basic block B) OUTPUT: IN[B] and OUT[B] for each basic block B METHOD: OUT[entry] = Φ for (each basic block B\entry) OUT[B] = Φ Worklist <- all basic blocks while(worklist is not empty) Pick a basic block B from Worklist old_OUT = OUT[B] IN[B] = ∪ (P: a predecessor of B) OUT[P] OUT[B] = gen(B) ∪ (IN[B] - kill(B)) if (old_OUT ≠ OUT[B]) Add all successors of B to Worklist
void foo() { Number n = new One(); int x = n.get(); }
interface Number { int get(); } class Zero implements Number { public int get() {return 0;} } class One implements Number { public int get() {return 1;} } class Two implements Number { public int get() {return 2;} }
class A { static void main() { A a = new A(); A b = new B(); A c = b.foo(a); } A foo(A x) { ... } } class B extends A { A foo(A y) { A r = new A(); return r; } }
一开始的时候WL为空,RM为空,CG为空。首先调用AddReachable函数把入口函数加入到可达图中,此时RM为{A.main()},在AddReachable仍需把main函数中的x = new T()形式的语句加入到WL中,WL中变为[<a, {o3}>, <b, {o4}>],再根据上边的指针分析算法进行分析。
struct redisServer { //上一次进行抽样的时间 long long ops_sec_last_sample_time; //上一次抽样时,服务器已执行命令的数量 long long ops_sec_last_sample_ops; // REDIS_OPS_SEC_SAMPLES 大小(默认值为16 )的环形数组, //数组中的每个项都记录了一次抽样结果。 long long ops_sec_samples[REDIS_OPS_SEC_SAMPLES]; // ops_sec_samples 数组的索引值, //每次抽样后将值自增一, //在值等于16 时重置为0 , //让ops_sec_samples 数组构成一个环形数组。 int ops_sec_idx; // ... };
在发送SLAVEOF no one命令之后,领头Sentinel会以每秒一次的频率(平时是每十秒一次),向被升级的从服务器发送INFO命令,并观察命令回复中的角色(role)信息,当被升级服务器的role从原来的slave变为master时,领头Sentinel就知道被选中的从服务器已经顺利升级为主服务器了。 例如,在上图所展示的例子中,领头Sentinel会一直向server2发送INFO命令,当server2返回的命令回复从:
1 2 3 4 5
# Replication role:slave ... # Other sections ...
变为:
1 2 3 4 5
# Replication role:master ... # Other sections ...
def CLUSTER_ADDSLOTS(*all_input_slots): # 遍历所有输入槽,检查它们是否都是未指派槽 for i in all_input_slots: # 如果有哪怕一个槽已经被指派给了某个节点 # 那么向客户端返回错误,并终止命令执行 if clusterState.slots[i] != NULL: reply_error() return
# 如果所有输入槽都是未指派槽 # 那么再次遍历所有输入槽,将这些槽指派给当前节点 for i in all_input_slots: # 设置clusterState 结构的slots 数组 # 将slots[i]的指针指向代表当前节点的clusterNode 结构 clusterState.slots[i] = clusterState.myself
classSolution: # 这里要特别注意~找到任意重复的一个值并赋值到duplication[0] # 函数返回True/False defduplicate(self, numbers, duplication): ifnot numbers: returnFalse for _, v inenumerate(numbers): if v >= len(numbers) or v < 0: returnFalse for i inrange(len(numbers)): while numbers[i] != i: if numbers[i] == numbers[numbers[i]]: duplication[0] = numbers[i] returnTrue else: idx = numbers[i] numbers[i], numbers[idx] = numbers[idx], numbers[i] returnFalse
使用 O(1) 空间的解法: 但条件一定要明确,存在重复数字。思维类似于寻找链表环的入口。
1 2 3 4 5 6 7 8 9 10 11
classSolution: defduplicateInArray(self, nums): f = s = 0 while f == 0or f != s: f = nums[nums[f]] s = nums[s] f = 0 while f != s: f = nums[f] s = nums[s] return s
classSolution(object): defhasPath(self, matrix, string): ifnot matrix ornot matrix[0] ornot string: returnFalse m, n = len(matrix), len(matrix[0]) state = [[True] * n for _ inrange(m)]
defdfs(i, j, pos): if0 <= i < m and0 <= j < n and state[i][j]: state[i][j] = ret = False if matrix[i][j] == string[pos]: if pos == len(string) - 1: returnTrue ret = dfs(i, j-1, pos+1) or dfs(i, j+1, pos+1) or dfs(i-1, j, pos+1) or dfs(i+1, j, pos+1) ifnot ret: state[i][j] = True return ret
for i inrange(m): for j inrange(n): if matrix[i][j] == string[0]: if dfs(i, j, 0): returnTrue returnFalse
实现函数double Power(double base, int exponent),求base的 exponent次方。不得使用库函数,同时不需要考虑大数问题。
解法:
1 2 3 4 5 6 7 8 9 10
classSolution: # 简单快速幂解法 defPower(self, base, exponent): exp = abs(exponent) r = 1 while exp: if exp & 1: r *= base base *= base exp >>= 1 return r if exponent >= 0else1/r
classSolution(object): defisMatch(self, s, p): dp = [[False] * (len(p)+1) for _ inrange(len(s)+1)] dp[0][0] = True for j inrange(1, len(p)+1): if p[j-1] == '*': dp[0][j] = dp[0][j-2] for i inrange(1, len(s)+1): for j inrange(1, len(p)+1): if p[j-1] != '*': dp[i][j] = dp[i-1][j-1] and p[j-1] in (s[i-1], '.') else: dp[i][j] = dp[i][j-2] or dp[i-1][j] and p[j-2] in (s[i-1], '.') return dp[-1][-1]
for c in s: if c.isdigit(): isFirst = False continue if c notin validList: returnFalse if c == 'e'or c == 'E': if isFirst: returnFalse isFirst = True validList = set(['+', '-']) if c == '.': validList = set(['e', 'E']) if c == '+'or c == '-': ifnot isFirst: returnFalse validList.remove('+') validList.remove('-')
# class ListNode: # def __init__(self, x): # self.val = x # self.next = None
classSolution: deffindKthToTail(self, head, k): ifnot head or k <= 0: returnNone fast = slow = head for _ inrange(k): # 快慢指针来走,之所以先判断是为了防止 k 等于链表长度的情况。 ifnot fast: returnNone fast = fast.next while fast: fast, slow = fast.next, slow.next return slow
# class ListNode: # def __init__(self, x): # self.val = x # self.next = None classSolution: defEntryNodeOfLoop(self, pHead): pre = post = pHead while pre and pre.next: # 确保快指针有意义没有到头 post = post.next# 慢指针走一步 pre = pre.next.next# 快指针走两步 if pre == post: # 相遇的时候即是有环 post = pHead # 慢指针再从头走 while pre != post: # 两个指针都是每次一步直到相遇 pre = pre.next post = post.next return post # 相遇的地方即是环的入口 returnNone
classSolution: defisPopOrder(self, pushV, popV): iflen(pushV) != len(popV): returnFalse stack, i = [], 0# 用 stack 来模拟进出栈。 for v in pushV: stack.append(v) while stack and stack[-1] == popV[i]: stack.pop() i += 1 returnnot stack
# class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None classSolution: # 返回从上到下每个节点值列表,例:[1,2,3] defPrintFromTopToBottom(self, root): res = [] if root: level = [root] while level: res.extend([x.val for x in level]) level = [leaf for node in level for leaf in (node.left, node.right) if leaf] return res
classSolution: defpermutation(self, nums): perms = [[]] for n in nums: perms = [ p[:i] + [n] + p[i:] for p in perms for i inrange((p+[n]).index(n)+1)] return perms
classSolution: defFindGreatestSumOfSubArray(self, array): best = cur = array[0] for i inrange(1, len(array)): cur = max(array[i], array[i] + cur) best = max(best, cur) return best
classSolution: defnumberOf1Between1AndN_Solution(self, n): count, i = 0, 1 while i <= n: a, b = n // i, n % i count += (a+8) // 10 * i + (a%10 == 1) * (b+1) i *= 10 return count
classSolution(object): # 快速跳过不用检查的位数,确定区间。 defdigitAtIndex(self, n): n -= 1 for digit inrange(1, 11): first = 10 ** (digit - 1) if n < 9 * first * digit: returnint(str(first + n // digit)[n % digit]) n -= 9 * first * digit
classSolution: defgetTranslationCount(self, s): ifnot s: return0 l = r = 1 for i inrange(len(s)-2, -1, -1): if s[i] == '1'or s[i] == '2'and s[i+1] < '6': l, r = l + r, l else: r = l return l
classSolution: deflengthOfLongestSubstring(self, s): start = maxLength = 0 used = {} for i, c inenumerate(s): if c in used and start <= used[c]: start = used[c] + 1 else: maxLength = max(maxLength, i - start + 1) used[c] = i return maxLength
classSolution: # 面试用装x解法 deffindNumberAppearingOnce(self, nums): a = b = 0 for n in nums: a = (a ^ n) & ~b b = (b ^ n) & ~a return a
1 2 3 4 5 6 7 8 9 10 11
classSolution: # 常规解法 deffindNumberAppearingOnce(self, nums): ans = 0 for i inrange(32): cnt = 0 for n in nums: if (n >> i) & 1: cnt += 1 if cnt % 3: ans |= 1 << i return ans if ans < 2**31else ans - 2**32
classSolution: defmaxSlidingWindow(self, nums: List[int], k: int) -> List[int]: dq = collections.deque() # 使用双向队列解决本题 res = [] for i, v inenumerate(nums): while dq and nums[dq[-1]] < v: # dq中如果存在多个元素 dq.pop() # 一定是降序排列的 dq += i, if dq[0] == i - k: # 判断dq中第一位是否有效 dq.popleft() if i >= k - 1: # 满足滑动窗口长度才有输出 res += nums[dq[0]], return res