1. 道路的最大总重要性
给你一个整数 n
,表示一个国家里的城市数目。城市编号为 0
到 n - 1
。
给你一个二维整数数组 roads
,其中 roads[i] = [ai, bi]
表示城市 ai
和 bi
之间有一条 双向 道路。
你需要给每个城市安排一个从 1
到 n
之间的整数值,且每个值只能被使用 一次 。道路的 重要性 定义为这条道路连接的两座城市数值 之和 。
请你返回在最优安排下,所有道路重要性 之和 最大 为多少。
Example 1
输入:n = 5, roads = [[0,1],[1,2],[2,3],[0,2],[1,3],[2,4]]
输出:43
Example 2
输入:n = 5, roads = [[0,3],[2,4],[1,3]]
输出:20
Constraints:
2 <= n <= 5 * 10^4
1 <= roads.length <= 5 * 10^4
roads[i].length == 2
0 <= ai, bi <= n - 1
ai != bi
- 没有重复道路。
代码 [贪心]
class Solution {
public:
long long maximumImportance(int n, vector<vector<int>> &roads) {
vector<int> nums(n, 0);
for (auto &road:roads) ++nums[road[0]], ++nums[road[1]];
sort(nums.begin(), nums.end());
long long result = 0, cnt = 1;
for (int num:nums) result += cnt++ * num;
return result;
}
};
2. 最长快乐字符串
A string s
is called happy if it satisfies the following conditions:
s
only contains the letters'a'
,'b'
, and'c'
.s
does not contain any of"aaa"
,"bbb"
, or"ccc"
as a substring.s
contains at mosta
occurrences of the letter'a'
.s
contains at mostb
occurrences of the letter'b'
.s
contains at mostc
occurrences of the letter'c'
.
Given three integers a
, b
, and c
, return the longest possible happy string. If there are multiple longest happy strings, return any of them. If there is no such string, return the empty string ""
.
A substring is a contiguous sequence of characters within a string.
Example 1
Input: a = 1, b = 1, c = 7
Output: "ccaccbcc"
Explanation: "ccbccacc" would also be a correct answer.
Example 2
Input: a = 7, b = 1, c = 0
Output: "aabaa"
Explanation: It is the only correct answer in this case.
Constraints:
0 <= a, b, c <= 100
a + b + c > 0
代码 [贪心]
class Solution {
public:
string longestDiverseString(int a, int b, int c) {
string ans;
vector<tuple<int, char>> arr = {{a, 'a'}, {b, 'b'}, {c, 'c'}};
while (get<0>(arr[0]) || get<0>(arr[1]) || get<0>(arr[2])) {
sort(arr.begin(), arr.end());
auto&[cnt2, ch2]=arr[2];
auto&[cnt1, ch1]=arr[1];
if (ans.size() < 2 || ans.back() != ch2 || ans[ans.size() - 2] != ch2) {
ans.push_back(ch2);
--cnt2;
} else if (cnt1 != 0) {
ans.push_back(ch1);
--cnt1;
} else {
return ans;
}
}
return ans;
}
};
3. 为高尔夫比赛砍树
You are asked to cut off all the trees in a forest for a golf event. The forest is represented as an m x n
matrix. In this matrix:
0
means the cell cannot be walked through.1
represents an empty cell that can be walked through.- A number greater than
1
represents a tree in a cell that can be walked through, and this number is the tree’s height.
In one step, you can walk in any of the four directions: north, east, south, and west. If you are standing in a cell with a tree, you can choose whether to cut it off.
You must cut off the trees in order from shortest to tallest. When you cut off a tree, the value at its cell becomes 1
(an empty cell).
Starting from the point (0, 0)
, return the minimum steps you need to walk to cut off all the trees. If you cannot cut off all the trees, return -1
.
You are guaranteed that no two trees have the same height, and there is at least one tree needs to be cut off.
Example 1
Input: forest = [[1,2,3],[0,0,4],[7,6,5]]
Output: 6
Example 2
Input: forest = [[1,2,3],[0,0,0],[7,6,5]]
Output: -1
Constraints:
m == forest.length
n == forest[i].length
1 <= m, n <= 50
0 <= forest[i][j] <= 10^9
代码 1 [排序+BFS 超时
]
class Solution {
private:
static constexpr pair<int, int> DIR[4]{{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
bool visited[50][50];
int bfs(const vector<vector<int>> &forest, int x0, int y0, int x1, int y1) {
memset(visited, 0, sizeof visited);
auto check = [&](int x, int y) {
return x >= 0 && y >= 0 && x < forest.size() && y < forest[0].size() && forest[x][y] != 0 && !visited[x][y];
};
queue<pair<int, int>> q;
int path = 0;
q.emplace(x0, y0);
while (!q.empty()) {
int size = q.size();
while (size--) {
auto[xc, yc]=q.front();
visited[xc][yc] = true;
q.pop();
if (xc == x1 && yc == y1) return path;
for (int i = 0; i < 4; ++i) {
auto[dx, dy]=DIR[i];
if (check(xc + dx, yc + dy)) q.emplace(xc + dx, yc + dy);
}
}
path++;
}
return -1;
}
public:
int cutOffTree(const vector<vector<int>> &forest) {
vector<int> tree;
for (int i = 0; i < forest.size(); ++i) {
for (int j = 0; j < forest[0].size(); ++j) {
if (forest[i][j] > 1) tree.push_back((i << 6) | j);
}
}
sort(tree.begin(), tree.end(), [&](int lo, int hi) {
return forest[lo >> 6][lo & 63] < forest[hi >> 6][hi & 63];
});
int p0 = 0, cnt = 0;
for (auto pn:tree) {
int cost = bfs(forest, p0 >> 6, p0 & 63, pn >> 6, pn & 63);
if (cost == -1) return -1;
cnt += cost;
p0 = pn;
}
return cnt;
}
};
4. 分割数组为连续子序列
给你一个按升序排序的整数数组 num
(可能包含重复数字),请你将它们分割成一个或多个长度至少为 3 的子序列,其中每个子序列都由连续整数组成。
如果可以完成上述分割,则返回 true
;否则,返回 false
。
Example 1
输入: [1,2,3,3,4,5]
输出: True
解释:
你可以分割出这样两个连续子序列 :
1, 2, 3
3, 4, 5
Constraints:
1 <= nums.length <= 10000
代码 1 [哈希]
class Solution {
private:
using pue = priority_queue<int, vector<int>, greater<>>;
public:
bool isPossible(vector<int> &nums) {
unordered_map<int, pue> mp;
for (auto x:nums) {
if (!mp.count(x)) mp[x] = pue();
if (mp.count(x - 1)) {
int prevLength = mp[x - 1].top();
mp[x - 1].pop();
if (mp[x - 1].empty()) mp.erase(x - 1);
mp[x].push(prevLength + 1);
} else {
mp[x].push(1);
}
}
return all_of(mp.begin(), mp.end(), [](const pair<int, pue> &val) {
return val.second.top() >= 3;
});
}
};
代码 2 [贪心]
class Solution {
public:
bool isPossible(vector<int> &nums) {
unordered_map<int, int> countMap, endMap;
for (auto x:nums) ++countMap[x];
for (auto x:nums) {
if (countMap[x]-- > 0) {
if (endMap[x - 1] > 0) {
--endMap[x - 1], ++endMap[x];
} else {
if (countMap[x + 1] > 0 && countMap[x + 2] > 0) {
--countMap[x + 1], --countMap[x + 2], ++endMap[x + 2];
} else {
return false;
}
}
}
}
return true;
}
};