# Leetcode notes -- Introduction to greedy algorithm

Posted by hopelessX on Thu, 24 Feb 2022 13:02:34 +0100

# preface

The question brushing route comes from: Code Capriccio
Greedy algorithm: the local optimal solution is stacked into the global optimal solution. There is no fixed routine. It is common sense derivation and counter examples.

# 1, Simple topic

## 455. Distribution of biscuits

Suppose you are a great parent and want to give your children some cookies. However, each child can only give one biscuit at most.
For each child I, there is an appetite value g[i], which is the minimum size of biscuits that can satisfy the children's appetite; And every cookie j has a size s[j]. If s[j] > = g[i], we can assign this biscuit j to child I, and the child will be satisfied. Your goal is to meet as many children as possible and output this maximum value. Solution:

```class Solution {
public int findContentChildren(int[] g, int[] s) {
// Sort first
Arrays.sort(g);
Arrays.sort(s);
int i = 0; // Child subscript
int j = 0; // Appetite subscript
while (i < g.length && j < s.length) {
if (s[j] >= g[i]) {
// Biscuits satisfy a child's appetite
i++;
j++;
} else {
// The child has too much appetite and looks back for big biscuits
j++;
}
}
return i;
}
}
```

## 1005. Maximum array sum after K negations

Give you an integer array nums and an integer k. modify the array as follows:
Select a subscript i and replace num [i] with - num [i].
Repeat this process exactly k times. You can select the same subscript i multiple times. After modifying the array in this way, the maximum possible sum of the array is returned Solution:
Invert the smallest number every time

```class Solution {
public int largestSumAfterKNegations(int[] nums, int k) {
for (int i = 0; i < k; i++) {
// Sort, reverse
Arrays.sort(nums);
nums = -nums;
}
// Sum
int sum = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
}
return sum;
}
}
```

Optimization:

```class Solution {
public int largestSumAfterKNegations(int[] nums, int k) {
// Sort first
Arrays.sort(nums);
// Invert the negative number in the [0,k) range
for (int i = 0; i < nums.length; i++) {
if (k > 0 && nums[i] < 0) {
nums[i] = -nums[i];
k--;
}
}
// See if the remaining k is even or odd
if (k % 2 == 1) {
// Odd number, invert the smallest number
Arrays.sort(nums);
nums = -nums;
}
// Even number without operation
// Sum
int sum = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
}
return sum;
}
}
```

At the lemonade stand, each glass of lemonade costs \$5. Customers line up to buy your products, one cup at a time (in the order bill is paid).
Each customer buys only one glass of lemonade and then pays you \$5, \$10 or \$20. You must give each customer the correct change, which means that the net transaction is \$5 per customer. Note that you don't have any change at first. Give you an integer array bills, where bills[i] is the bill paid by the ith customer. If you can give each customer the correct change, return true, otherwise return false. Solution:
Record the number of chapters of five yuan and ten yuan, and change the money according to the situation. When changing the money, the code is concise, and it is not necessary to judge whether there is money in hand. After finding the money, it is judged according to the positive and negative number of money.

```class Solution {
int five = 0;
int ten = 0;
for (int i = 0; i < bills.length; i++) {
// Case 1 Received 5 yuan
if (bills[i] == 5) {
five++;
}
// Case 2 Receive 10 yuan, change 5 quickly
if (bills[i] == 10) {
five--;
ten++;
}
// Situation 3 Got 20, 10 fast, find the fast one first
if (bills[i] == 20) {
if (ten > 0) {
ten--;
five--;
} else {
five -= 3;
}
}
// judge
if (five < 0 || ten < 0) {
return false;
}
}
return true;
}
}
```

# 2, Medium topic

## 376. Swing sequence

If the difference between consecutive numbers strictly alternates between positive and negative numbers, the number sequence is called swing sequence. The first difference (if any) may be positive or negative. A sequence with only one element or two unequal elements is also regarded as a swing sequence.
For example, [1, 7, 4, 9, 2, 5] is a swing sequence because the difference (6, - 3, 5, - 7, 3) is alternating positive and negative.
On the contrary, [1, 4, 7, 2, 5] and [1, 7, 4, 5, 5] are not swing sequences. The first sequence is because its first two differences are positive, and the second sequence is because its last difference is zero.
Subsequences can be obtained by deleting some (or no) elements from the original sequence, and the remaining elements maintain their original order.
Give you an integer array nums, which returns the length of the longest subsequence of the swing sequence in nums. Solution:
Two consecutive pairs of differences are opposite, indicating swing In special case, the longest swing subsequence of [2,2,5] is [2,5], but the difference is [0,5], so it is necessary to add equal to

```class Solution {
public int wiggleMaxLength(int[] nums) {
if (nums.length <= 1) return nums.length;
int preDiff = 0; // Last pair difference
int curDiff = 0; // Current difference
int count = 1; // record
for (int i = 1; i < nums.length; i++) {
curDiff = nums[i] - nums[i - 1];
// The difference between two consecutive pairs is opposite. Note that it is equal to
if ((curDiff > 0 && preDiff <= 0) || (curDiff < 0 && preDiff >= 0)) {
count++;
preDiff = curDiff;
}
}
return count;
}
}
```

## 738. Monotonically increasing numbers

Leetcode link Solution:
Local optimization: when strNum[i - 1] > strNum[i], let strNum[i - 1] –, and then strNum[i] is 9
Traverse from the back to the front to find the position where you start to assign 9

```class Solution {
public int monotoneIncreasingDigits(int n) {
if (n == 0) return 0;
// Convert to char array
char[] chars = String.valueOf(n).toCharArray();
int start = 10;  // Maximum
// Traverse from back to front
for (int i = chars.length - 1; i > 0; i--) {
if (chars[i] < chars[i - 1]) {
chars[i - 1]--;
start = i;
}
}
// Splicing
StringBuilder sb = new StringBuilder();
for (int i = 0; i < chars.length; i++) {
// 10 - > 09, the first 0 is not spliced
if (i == 0 && chars[i] == '0') continue;
if (i >= start) {
sb.append('9');
} else {
sb.append(chars[i]);
}
}
return Integer.valueOf(sb.toString());
}
}
```

## 122. The best time to buy and sell stocks II

Give an array prices, where prices[i] represents the price of the stock on day I. On each day, you may decide to buy and / or sell shares. You can only hold at most one share at any time. You can also buy it and sell it on the same day. Return the maximum profit you can make. Solution:
Local optimization: collect the positive profit every day. As long as the stock price is greater than that of the previous day, it will be counted as profit
Global Optimization: obtain the maximum profit.

```class Solution {
public int maxProfit(int[] prices) {
int res = 0;
for (int i = 1; i < prices.length; i++) {
if (prices[i] > prices[i - 1]) {
res += prices[i] - prices[i - 1];
}
}
return res;
}
}
```

## 714. The best time to buy and sell stocks includes handling fees

Give an integer array prices, where prices[i] represents the stock price on day I; The integer fee represents the handling fee for trading stocks. You can complete transactions indefinitely, but you need to pay a handling fee for each transaction. If you have bought a stock, you can't continue to buy it until you sell it. Returns the maximum profit. Solution:
The purchase price plus handling fee is the purchase price of the previous day.
Different from the above question, we can't calculate the daily profit without brains. For example: [1, 4, 8], when fee = 2, buy it at the price of 1 + 2 = 3. It can't be sold the next day, and then sell it again on the third three days with only one handling charge. How to calculate it? It can be assumed that 3 yuan is bought on the first day and 4 yuan is sold on the second day. The selling price is recorded. Because the price on the third day is greater than 4, it is calculated according to (8 - 4) on the third day, and the handling fee is less
When is the real sale? When [1, 6, 3, 8], 6 - (1 + 2) + 8 - (3 + 2) > 8 - (1 + 2). Because 3 + 2 < 6, the buying price on the third day is 5 yuan, which is less than the selling price of the previous day by 6 yuan.

```class Solution {
public int maxProfit(int[] prices, int fee) {
int sum = 0;
// Initialize to the buying price of the first day
int buy = prices + fee;
for (int i = 1; i < prices.length; i++) {
// If you can make a profit, calculate the profit, and record the price of this false sale as the next purchase price
} else if (prices[i] + fee < buy) {
}
}
return sum;
}
}
```

# 4, Two dimensional trade-off problem

## 135. Distribution of candy Solution:
Local optimization: if both sides consider together, they will consider one side at a time.

1. Traverse from left to right. As long as the score on the right is greater than that on the left, the child on the right will have one more candy
2. Traverse from right to left. As long as the score on the left is greater than that on the right, the child on the left will have one more candy
3. Traverse again, and take the maximum value of the first two traversals for each position
```class Solution {
public int candy(int[] ratings) {
int[] candyArr = new int[ratings.length];
candyArr = 1;
// The number of candy for the first child is 1 by default, starting from the second child
for (int i = 1; i < ratings.length; i++) {
candyArr[i] = ratings[i] > ratings[i - 1] ? candyArr[i - 1] + 1 : 1;
}
// The backward forward traversal starts from the penultimate child, and the last position is the result of more than one round of traversal
for (int i = ratings.length - 2; i >= 0; i--) {
int temp = ratings[i] > ratings[i + 1] ? candyArr[i + 1] + 1 : 1;
candyArr[i] = Math.max(temp, candyArr[i]);
}
int res = 0;
for (int i = 0; i < candyArr.length; i++) {
res += candyArr[i];
}
return res;
}
}
```

## 406. The cohort was reconstructed according to height

Suppose a group of people who are out of order stand in a queue, and the array people represents the attributes of some people in the queue (not necessarily in order). Each person [i] = [Hi, Ki] means that the height of the ith person is hi, and there is just ki person whose height is greater than or equal to hi in front. Please reconstruct and return the queue represented by the input array people. The returned queue should be formatted as an array queue, where queue[j] = [hj, kj] is the attribute of the jth person in the queue (queue is the person in front of the queue). Solution:
Sort by height before inserting

```class Solution {
public int[][] reconstructQueue(int[][] people) {
Arrays.sort(people, (p1, p2) -> {
// Same, in ascending order of the second element
if (p1 == p2) return p1 - p2;
// Default descending order
return p2 - p1;
});