Journey of LeetCode|DAY 29
Preface
This is a new day to continue my Greedy Algorithm journey.
Learn something new and keep reviewing what I learnt before.
1. Maximize Sum Of Array After K Negations
LeetCode Link: 1005. Maximize Sum Of Array After K Negations
Given an integer array nums and an integer k, modify the array in the following way:
choose an index i and replace nums[i] with -nums[i].
You should apply this process exactly k times. You may choose the same index i multiple times.
Return the largest possible sum of the array after modifying it in this way.
Example 1:
Input: nums = [4,2,3], k = 1
Output: 5
Explanation: Choose index 1 and nums becomes [4,-2,3].
Example 2:
Input: nums = [3,-1,0,2], k = 3
Output: 6
Explanation: Choose indices (1, 2, 2) and nums becomes [3,1,0,2].
Example 3:
Input: nums = [2,-3,-1,5,-4], k = 2
Output: 13
Explanation: Choose indices (1, 4) and nums becomes [2,3,-1,5,4].
Constraints:
1 <= nums.length <= 104
-100 <= nums[i] <= 100
1 <= k <= 104
Analysis and Solution
Greedy Algorithm
LeetCode C++ as followings Greedy Algorithm
class Solution {
static bool cmp(int a, int b) {
return abs(a) > abs(b);
}
public:
int largestSumAfterKNegations(vector<int>& A, int K) {
sort(A.begin(), A.end(), cmp); // Sort the array from big to small according to the absolute value, pay attention to the size of the absolute value
for (int i = 0; i < A.size(); i++) { // Traversing from front to back, when encountering a negative number, turn it into a positive number, and K--
if (A[i] < 0 && K > 0) {
A[i] *= -1;
K--;
}
}
if (K % 2 == 1) A[A.size() - 1] *= -1; // If K is still greater than 0, then repeatedly transform the element with the smallest value to consume K
int result = 0;
for (int a : A) result += a; // get sum
return result;
}
};
2. Gas Station
LeetCode Link: 134. Gas Station
There are n gas stations along a circular route, where the amount of gas at the ith station is gas[i].
You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from the ith station to its next (i + 1)th station. You begin the journey with an empty tank at one of the gas stations.
Given two integer arrays gas and cost, return the starting gas station’s index if you can travel around the circuit once in the clockwise direction, otherwise return -1. If there exists a solution, it is guaranteed to be unique
Example 1:
Input: gas = [1,2,3,4,5], cost = [3,4,5,1,2]
Output: 3
Explanation:
Start at station 3 (index 3) and fill up with 4 unit of gas. Your tank = 0 + 4 = 4
Travel to station 4. Your tank = 4 - 1 + 5 = 8
Travel to station 0. Your tank = 8 - 2 + 1 = 7
Travel to station 1. Your tank = 7 - 3 + 2 = 6
Travel to station 2. Your tank = 6 - 4 + 3 = 5
Travel to station 3. The cost is 5. Your gas is just enough to travel back to station 3.
Therefore, return 3 as the starting index.
Example 2:
Input: gas = [2,3,4], cost = [3,4,3]
Output: -1
Explanation:
You can’t start at station 0 or 1, as there is not enough gas to travel to the next station.
Let’s start at station 2 and fill up with 4 unit of gas. Your tank = 0 + 4 = 4
Travel to station 0. Your tank = 4 - 3 + 2 = 3
Travel to station 1. Your tank = 3 - 3 + 3 = 3
You cannot travel back to station 2, as it requires 4 unit of gas but you only have 3.
Therefore, you can’t travel around the circuit once no matter where you start.
Constraints:
n == gas.length == cost.length
1 <= n <= 105
0 <= gas[i], cost[i] <= 104
Analysis and Solution
Violent Solution
LeetCode C++ as followings Violent Solution
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
for (int i = 0; i < cost.size(); i++) {
int rest = gas[i] - cost[i]; // record remaining gas
int index = (i + 1) % cost.size();
while (rest > 0 && index != i) { // Simulate driving around starting from i (if rest==0, then the answer is not unique)
rest += gas[index] - cost[index];//get remaining gas
index = (index + 1) % cost.size();
}
// If you run around with i as the starting point, and the remaining gas is >=0, return to the starting position
if (rest >= 0 && index == i) return i;
}
return -1;
}
};
Greedy Algorithm
LeetCode C++ as followings Greedy Algorithm
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int curSum = 0;//to record sum of remaining gas
int totalSum = 0;//to record sum of accumulated rest[i]=gas[i]-cost[i]
int start = 0;
for (int i = 0; i < gas.size(); i++) {
curSum += gas[i] - cost[i];
totalSum += gas[i] - cost[i];
if (curSum < 0) { // Once the current accumulated rest[i] and curSum are less than 0
start = i + 1; // The starting position is updated to i+1
curSum = 0; // curSum starts from 0
}
}
if (totalSum < 0) return -1; // indicates that cannot make it done
return start;
}
};
3. Candy
LeetCode Link: 135. Candy
There are n children standing in a line. Each child is assigned a rating value given in the integer array ratings.
You are giving candies to these children subjected to the following requirements:
Each child must have at least one candy.
Children with a higher rating get more candies than their neighbors.
Return the minimum number of candies you need to have to distribute the candies to the children.
Example 1:
Input: ratings = [1,0,2]
Output: 5
Explanation: You can allocate to the first, second and third child with 2, 1, 2 candies respectively.
Example 2:
Input: ratings = [1,2,2]
Output: 4
Explanation: You can allocate to the first, second and third child with 1, 2, 1 candies respectively.
The third child gets 1 candy because it satisfies the above two conditions.
Constraints:
n == ratings.length
1 <= n <= 2 * 104
0 <= ratings[i] <= 2 * 104
Analysis and Solution
Greedy Algorithm
LeetCode C++ as followings Greedy Algorithm
class Solution {
public:
int candy(vector<int>& ratings) {
vector<int> candyVec(ratings.size(), 1);
// from front to back
for (int i = 1; i < ratings.size(); i++) {
if (ratings[i] > ratings[i - 1]) candyVec[i] = candyVec[i - 1] + 1;//If ratings[i] > ratings[i - 1] then [i] must have one more candy than [i - 1], so greedy Algorithm: candyVec[i] = candyVec[i - 1] + 1
}
// from back to front
for (int i = ratings.size() - 2; i >= 0; i--) {//If ratings[i] > ratings[i + 1], at this time candyVec[i] (the number of candies for the i-th child) has two options, one is candyVec[i + 1] + 1 (from the one on the right) The number of candies obtained by 1), one is candyVec[i] (the number of candies obtained by the right child is greater than that of the left child).
if (ratings[i] > ratings[i + 1] ) {
candyVec[i] = max(candyVec[i], candyVec[i + 1] + 1);//Take candyVec[i + 1] + 1 and candyVec[i] with the largest number of candies. CandyVec[i] only takes the largest candy to keep more candies on the left candyVec[i - 1] than the right candyVec[i + 1] ] of candy.
}
}
// get result
int result = 0;
for (int i = 0; i < candyVec.size(); i++) result += candyVec[i];
return result;
}
};