@TOC

# foreword

Code Caprice Algorithm Training Camp day34

# 1. Leetcode 1005. The array sum maximized after K inversions

## 1. Topic

Given an array of integers nums and an integer k, modify the array as follows:

`选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。`

Repeat this process exactly k times. The same subscript i can be selected multiple times.

After modifying an array in this way, return the largest sum possible for the array.

Example 1:

Input: nums = [4,2,3], k = 1 Output: 5 Explanation: Select subscript 1, nums becomes [4,-2,3].

Example 2:

Input: nums = [3,-1,0,2], k = 3 Output: 6 Explanation: Select subscript (1, 2, 2), nums becomes [3,1,0,2].

Example 3:

Input: nums = [2,-3,-1,5,-4], k = 2 Output: 13 Explanation: Select subscript (1, 4), nums becomes [2,3,-1,5,4 ].

Source: LeetCode Link: https://leetcode.cn/problems/maximize-sum-of-array-after-k-negations

## 2. Problem-solving ideas

Method 1: Modify each negative number from small to large

Ideas and Algorithms

Since we want the sum of the arrays to be as large as possible, unless it is absolutely necessary, we should always modify negative numbers, and preferentially modify the negative numbers with the smallest value. Because changing the negative number −x−x to xx will increase the sum of the array by 2x2x, such a greedy operation is optimal.

When the given KK is less than or equal to the number of negative numbers in the array, we can modify each negative number in order from small to large according to the above method. But if the value of KK is larger, then we have to modify the non-negative number (ie positive number or 00). Since modifying 00 has no effect on the sum of the array, and modifying positive numbers will reduce the sum of the array, therefore:

```
如果数组中存在 00，那么我们可以对它进行多次修改，直到把剩余的修改次数用完；
如果数组中不存在 00 并且剩余的修改次数是偶数，由于对同一个数修改两次等价于不进行修改，因此我们也可以在不减小数组的和的前提下，把修改次数用完；
如果数组中不存在 00 并且剩余的修改次数是奇数，那么我们必然需要使用单独的一次修改将一个正数变为负数(剩余的修改次数为偶数，就不会减小数组的和)。为了使得数组的和尽可能大，我们就选择那个最小的正数。
需要注意的是，在之前将负数修改为正数的过程中，可能出现了(相较于原始数组中最小的正数)更小的正数，这一点不能忽略。
```

detail

In order to implement the above algorithm, we can sort the array in ascending order, first traverse each negative number in turn (change the negative number to a positive number), and then traverse all the numbers (modify 00 or the smallest positive number).

However, notice that the range of array elements in this question is [−100,100][−100,100], so we can use counting arrays (buckets) or hash tables to directly count the number of occurrences of each element, and then traverse the range of elements in ascending order, so that It saves the time required for sorting.

## 3. Code implementation

```java class Solution { public int largestSumAfterKNegations(int[] nums, int k) { Map freq = new HashMap(); for (int num : nums) { freq.put(num, freq.getOrDefault(num, 0) + 1); } int ans = Arrays.stream(nums).sum(); for (int i = -100; i < 0; ++i) { if (freq.containsKey(i)) { int ops = Math.min(k, freq.get(i)); ans += (-i) * ops * 2; freq.put(i, freq.get(i) - ops); freq.put(-i, freq.getOrDefault(-i, 0) + ops); k -= ops; if (k == 0) { break; } } } if (k > 0 && k % 2 == 1 && !freq.containsKey(0)) { for (int i = 1; i <= 100; ++i) { if (freq.containsKey(i)) { ans -= i * 2; break; } } } return ans; } }

```

# 2. Leetcode 134. Gas station

## 1. Topic

There are n gas stations on a loop, and the i-th gas station has gas[i] liters of gasoline.

You have a car with unlimited fuel tank capacity, and it takes cost[i] liters of gasoline to drive from the i-th gas station to the i+1-th gas station. You start off from one of the gas stations, starting with an empty tank.

Given two integer arrays gas and cost, return the number of the gas station at the time of departure if you can drive around the circle in order, otherwise return -1. If a solution exists, it is guaranteed to be unique.

Example 1:

Input: gas = [1,2,3,4,5], cost = [3,4,5,1,2] Output: 3 Explanation: Starting from gas station No. 3 (at index 3), you can get 4 liters of petrol. At this time, the fuel tank has = 0 + 4 = 4 liters of gasoline and is going to No. 4 gas station. At this time, the fuel tank has 4 - 1 + 5 = 8 liters of gasoline and is going to No. 0 gas station. At this time, the fuel tank has 8 - 2 + 1 = 7 liters of gasoline is going to No. 1 gas station, at this time there are 7 - 3 + 2 = 6 liters of gasoline in the fuel tank and it is going to No. 2 gas station, at this time the fuel tank is 6 - 4 + 3 = 5 liters of gasoline is going to No. It takes 5 liters of petrol, just enough to get you back to gas station #3. Therefore, 3 can be the starting index.

Example 2:

Input: gas = [2,3,4], cost = [3,4,3] Output: -1 Explanation: You cannot start from gas station 0 or 1, because there is not enough gas to drive you to the next a gas station. We start from gas station 2 and get 4 liters of gasoline. At this time, the fuel tank has = 0 + 4 = 4 liters of gasoline and is going to No. 0 gas station. At this time, the fuel tank has 4 - 3 + 2 = 3 liters of gasoline and is going to No. 1 gas station. At this time, the fuel tank has 3 - 3 + 3 = 3 You can't go back to gas station 2 because the return journey takes 4 liters of gasoline, but your tank only has 3 liters of gasoline. So, no matter what, you can't drive around the loop.

hint:

```
gas.length == n
cost.length == n
1 <= n <= 105
0 <= gas[i], cost[i] <= 104
```

## 2. Problem-solving ideas

Method 1: One time traversal

Ideas and Algorithms

The easiest solution to think of is: traverse each gas station from the beginning to the end, and check whether the gas station can be used as the starting point to travel for a week. We can reduce the overall time complexity by reducing the number of gas stations checked.

Suppose we found out before that starting from the gas station xx, we refuel every time we pass a gas station (including the starting gas station), and the last gas station that can be reached is yy (may set x

∑i=xygas[i]<∑i=xycost[i]∑i=xjgas[i]≥∑i=xjcost[i] (For all j∈[x,y)) i=x∑ygas[i]* *

The first expression indicates that the gas station next to gas station yy cannot be reached, and the second expression indicates that yy and all gas stations before yy are reachable.

Now, consider any gas station zz located between x, yx, y (including xx and yy), we now examine whether starting from this gas station can reach the next gas station of gas station yy, that is, to judge ∑ The magnitude relationship between i=zygas[i]∑i=zygas[i] and ∑i=zycost[i]∑i=zycost[i].

According to the above formula, we get:

∑i=zygas[i]=∑i=xygas[i]−∑i=xz−1gas[i]<∑i=xycost[i]−∑i=xz−1gas[i]<∑i=xycost[i]−∑i=xz−1cost[i]=∑i=zycost[i]i=z∑ygas[i]=i=x∑ygas[i]−i=x∑z−1gas[i]* *

The second and third steps of the inequality use the above first and second inequalities respectively.

From the above derivation, it can be concluded that starting from any gas station between x, yx, y, it is impossible to reach the next gas station of gas station yy.

After discovering this property, the algorithm is very clear: we first check the 00th gas station and try to judge whether it can go around; if not, we continue to check from the first unreachable gas station.

## 3. Code implementation

```java class Solution { public int canCompleteCircuit(int[] gas, int[] cost) { int n = gas.length; int i = 0; while (i < n) { int sumOfGas = 0, sumOfCost = 0; int cnt = 0; while (cnt < n) { int j = (i + cnt) % n; sumOfGas += gas[j]; sumOfCost += cost[j]; if (sumOfCost > sumOfGas) { break; } cnt++; } if (cnt == n) { return i; } else { i = i + cnt + 1; } } return -1; } }

```

# 3. Leetcode 135. Distribute candy

## 1. Topic

n children stand in a row. You are given an integer array ratings representing each child's rating.

You need to distribute candy to these children according to the following requirements:

```
每个孩子至少分配到 1 个糖果。
相邻两个孩子评分更高的孩子会获得更多的糖果。
```

Please distribute candies to each child, calculate and return the minimum number of candies that need to be prepared.

Example 1:

Input: ratings = [1,0,2] Output: 5 Explanation: You can distribute 2, 1, and 2 candies to the first, second, and third children, respectively.

Example 2:

Input: ratings = [1,2,2] Output: 4 Explanation: You can distribute 1, 2, and 1 candy to the first, second, and third children, respectively. The third child only gets 1 candy, which satisfies the two conditions in the title.

hint:

```
n == ratings.length
1 <= n <= 2 * 104
0 <= ratings[i] <= 2 * 104
```

Source: LeetCode Link: https://leetcode.cn/problems/candy

## 2. Problem-solving ideas

Method 1: Two traversals

Ideas and solutions

We can split the sentence "Among adjacent children, the child with the highest score must get more candies" into two rules and deal with them separately.

```
左规则：当 ratings[i−1]<ratings[i]ratings[i−1]<ratings[i] 时，ii 号学生的糖果数量将比 i−1i−1 号孩子的糖果数量多。
右规则：当 ratings[i]>ratings[i+1]ratings[i]>ratings[i+1] 时，ii 号学生的糖果数量将比 i+1i+1 号孩子的糖果数量多。
```

We traverse the array twice to process the minimum number of candies that need to be distributed when each student satisfies the left rule or the right rule respectively. The final amount of candy that each person gets is the maximum of these two amounts.

Specifically, take the left rule as an example: we traverse the array from left to right, assuming that we are currently traversing to position ii, if there is ratings[i−1]

In the actual code, we first calculate the array of the left rule leftleft. When calculating the right rule, we only need to use a single variable to record the right rule at the current position, and calculate the answer at the same time.

## 3. Code implementation

```java class Solution { public int candy(int[] ratings) { int n = ratings.length; int[] left = new int[n]; for (int i = 0; i < n; i++) { if (i > 0 && ratings[i] > ratings[i - 1]) { left[i] = left[i - 1] + 1; } else { left[i] = 1; } } int right = 0, ret = 0; for (int i = n - 1; i >= 0; i--) { if (i < n - 1 && ratings[i] > ratings[i + 1]) { right++; } else { right = 1; } ret += Math.max(left[i], right); } return ret; } }

```