来看配图版
将两个数组的字符串分别按序拼接,然后比较两字符串是否相等即可。
class Solution {
public:
bool arrayStringsAreEqual(vector& word1, vector& word2) {
string a = "", b = "";
for(auto w : word1) a += w;
for(auto w : word2) b += w;
return a == b;
}
};
时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( n ) O(n) O(n)。
题目说明了给定 n , k n, k n,k 一定能构造出字符串,所以先将所有 n n n 位都初始化为字符 a a a,一定是目前数值最小的字符串,维护一个变量 c n t cnt cnt 记录当前字符串数值,修改字符串从末尾开始增加(为了保证最小字典序),若最后一位已经修改到字符 z z z ,则倒数第二位开始增加,所以维护一个 p o s pos pos 变量记录当前需要修改的位置。直到 c n t = k cnt = k cnt=k 时结束。
class Solution {
public:
string getSmallestString(int n, int k) {
string res = "";
int cnt = 0;
for(int i = 0; i < n; i++) {
res += "a";
cnt++;
}
int pos = 1;
while(k > cnt) {
if(res[n - pos] == 'z') {
pos++;
}
res[n - pos]++;
k--;
}
return res;
}
};
时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( n ) O(n) O(n)。
由于删除一个数后,这个数后面所有数都向前挪动一位,所以原本奇数位的数变成了偶数位,偶数位的数变成了奇数位。那么对于一个删除的下标位置 i n d e x index index,删除该元素后, i n d e x index index后面所有奇数下标元素的和其实就是移除之前, i n d e x index index后面所有偶数下标元素的和。所以提前维护两个前缀和,分别记录奇数下标元素和偶数下标元素之和即可。
class Solution {
public:
int waysToMakeFair(vector& nums) {
int n = nums.size();
vector odd(n + 1, 0);
vector even(n + 1, 0);
for(int i = 1; i <= n; i++) {
if(i % 2 == 1) {
odd[i] = odd[i - 1];
even[i] = even[i - 1] + nums[i - 1];
} else {
odd[i] = odd[i - 1] + nums[i - 1];
even[i] = even[i - 1];
}
}
int cnt = 0;
for(int i = 0; i < n; i++) {
int o = odd[i] - odd[0] + even[n] - even[i + 1]; // 奇数下标元素之和
int e = even[i] - even[0] + odd[n] - odd[i + 1]; // 偶数下标元素之和
if(o == e) {
cnt++;
}
}
return cnt;
}
};
时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( n ) O(n) O(n)。
题目要求最少初始能量,我们反向考虑这个问题,假设初始能量 z = 0 z = 0 z=0。现在我们考虑要做的第一个任务 t a s k [ i ] = [ x , y ] task[i] = [x, y] task[i]=[x,y],为了开始执行这个任务,我们需要“补”差价,也就是补上 y y y 值的能量。最终完成所有任务需要补的能量之和就是题目要求的最少初始能量。在完成这个任务后,我们还剩余能量 y − x y - x y−x,此时我们需要继续去完成其他任务。当完成最后一个任务后,剩余的能量就没用了。所以,我们希望尽可能将剩余能量 y − x y - x y−x 较大的任务放在前面做,这样在完成一个任务后,我们为了完成下一个任务需要补的“差价”就少,同样地,我们把剩余能量较小的任务放在后面做,这样完成最后一个任务后,我们就不会“心疼”扔掉的能量了。
当两个任务 [ x 1 , y 1 ] , [ x 2 , y 2 ] ( y 1 < y 2 ) [x_1, y_1], [x_2, y_2](y_1 < y_2) [x1,y1],[x2,y2](y1<y2)具有相同的剩余能量 r r r 时,我们优先选择做 y y y 较大的任务,这是因为,完成两个任务后,剩余能量相等,假设先做了任务1,那么下面要做任务2,需要补差价 $ y_2 - r$, 而若是先做任务2,再做任务1时需要补的差价就是 y 1 − r y_1 - r y1−r,由于$ y_1 < y_2$, 故先做 y y y 较大的任务,需要补的差价就少了。
class Solution {
public:
struct task{
int x, y;
task(int x, int y):x(x), y(y){}
bool operator<(const task& a) const {
if(a.y - a.x == y - x) {
// 剩余能量相同,先做y较大的任务
return y < a.y;
}
// 先做剩余能量大的任务
return y - x < a.y - a.x;
}
};
int minimumEffort(vector>& tasks) {
priority_queue q;
for(auto t : tasks) { // 放入优先队列
task tmp(t[0], t[1]);
q.push(tmp);
}
// res 记录补差价总量,也即最终要求结果
// pos 记录当前剩余能量
int res = 0, pos = 0;
while(!q.empty())
{
task tmp = q.top();
if(pos >= tmp.y) { // 不用补差价
pos -= tmp.x;
} else {
res += tmp.y - pos;
pos = tmp.y - tmp.x;
}
q.pop();
}
return res;
}
};
时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( n ) O(n) O(n)。