LeetCode1005.K次取反后最大化的数组和
本题较为简单,一开始的思路是先从小到大排序,然后当处理完负数时,再重新从小到大排序,处理正数,或者维护一个绝对值最小的数的下标。
那么其实可以直接对nums进行绝对值排序,这样就不需要排序两遍了,需要自己额外定义一个cmp函数。
代码如下,时间复杂度即为排序算法时间复杂度;空间复杂度O(1).
class Solution {
public:
static bool cmp(int a,int b){
return abs(a)>abs(b);
}
int largestSumAfterKNegations(vector<int>& nums, int k) {
sort(nums.begin(),nums.end(),cmp);
int result = 0;
for(int i=0;i<nums.size();i++){
if(k>0 && nums[i]<0){
nums[i] = -nums[i];
k--;
}
result +=nums[i];
}
if(k%2==1){
result -= 2*nums[nums.size()-1];
}
return result;
}
};
LeetCode134. 加油站
本题通过将汽油和路程巧妙做差,相当于对一个数组进行处理。假使本题一定可以走完一圈,那么start位置一定会在我们遍历一遍数组之后被记录到,因为位置肯定是从curSum之后的一个位置开始的,如果最后没有记录到start值,需要判断totalSum,并且在返回start之前返回,表示不存在start值。
代码如下:时间复杂度O(n),空间复杂度O(1)。
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int curSum = 0;
int totalSum = 0;
int start = 0;
for(int i=0;i<gas.size();i++){
curSum += gas[i]-cost[i];
totalSum += gas[i]-cost[i];
if(curSum<0){
start = i+1;
curSum = 0;
}
}
if(totalSum < 0) return -1;
return start;
}
};
LeetCode135. 分发糖果
这道题两边一起比较一定会顾此失彼,举个例子,一个数需要与旁边两个数比较,当左边数大,右边数小时,不只需要对当前数做处理,还需要对前一个已经处理过的数再重新做处理,如果对于前一个数来说也是相同的情况,就会比较复杂了,因此应该一边一边的处理,由于当我们遍历的时候,需要与左边的数进行比较,这个特性就决定我们需要从后往前遍历,这样才能正确的更新左边数对应的糖果,同样的,利用从前往后遍历更新右边数对应的糖果,这样就能够得到正确的nums数组,最后输出和。
代码如下:时间复杂度O(n);空间复杂度O(n)。
class Solution {
public:
int candy(vector<int>& ratings) {
vector<int> nums(ratings.size(),1);
int result = 0;
for(int i=0;i<ratings.size()-1;i++){
if(ratings[i]<ratings[i+1] && nums[i]>=nums[i+1]){
nums[i+1] = nums[i]+1;
}
}
for(int i=ratings.size()-1;i>0;i--){
if(ratings[i-1]>ratings[i] && nums[i-1]<=nums[i]){
nums[i-1] = nums[i]+1;
}
}
for(int i=0;i<nums.size();i++){
result += nums[i];
}
return result;
}
};