# LeetCode 945. Make the array the only minimum increment

Keywords: Java github network less

# subject

Given an array of integers A, any A[i] is selected and incremented by 1 for each move operation.

Returns the minimum number of operations that make each value in A unique.

```Example 1:

Input: [1,2,2]
Output: 1
Interpretation: After a move operation, the array will become [1, 2, 3].
Example 2:

Input: [3,2,1,2,1,7]
Output: 6
Interpretation: After six move s, the array will become [3, 4, 1, 2, 5, 7].
```

You can see that a move operation of five or fewer times cannot make each value of an array unique.

```Tips:

0 <= A.length <= 40000
0 <= A[i] < 40000
```

Source: LeetCode

## Solving problems

### Idea 1 - Sort first, then add up the +1 operands needed for each two neighbors from left to right;

1. Arrays.sort(A) sort;
2. Compare and record the operands needed to change the latter number to the previous number + 1.

Example: If the order followed by 123455, start with the second number:

• First time: 1223455 at this time move+=2-1
• Second time: 1233455 at this time move+=3-2
• Third time: 1234455 at this time move+=4-3
• Fourth time: 1234555 does not require operation
• Fifth time: 1234565 at this time move+=6-5
• Sixth time: 1234567 at this time move+=7-6
Where:
• Time complexity: O(NlogN) N=A.length
• Spatial Complexity: O(1)

### Idea 2 - First count the number of operands that are accumulated sequentially, and the number of times each + 1 operation is the same.

1. Create a new array, new int[40001], and then count each number in A as a subscript;
2. Traversing through the new array, if the same number in 1 is greater than 0, the number after -1 is the number that these numbers need to be operated on by +1. Add the number after these +1 operations to the next statistic, and make the final number different by -1 each time.
3. After traversal, you need to check the number of maximum subscripts again. If the number is greater than 1, and -1 number needs to be + 1, you can use the sum formula of 1-n directly.
• Time complexity: O(N) N=max(A.length, max(A))
• Spatial Complexity: O(40001) or O(1)

Tips: The first step of the statistics actually implies sorting. Using the nature of natural numbers, the natural ordering of subscripts is a feature of arrays that can easily be ignored, such as letters (via char's -'a'operation) that go into arrays to avoid extra sorting.

### Idea 3 - Path compression; (from LeetCode review area, nice...)

1. Create a new array, new int[80000] (initialization value-1), because path compression is different from the statistics in method 2 (or statistical compression), where the operation of + 1 is compressed, but the number after + 1 needs a new array to record. If all the values in A are 39999, the final maximum number will be 79999;
2. Start traversing and record the findPath of the route points. This is a recursive method, which may be more circular, analyzed separately:
```private int findPath(int i) {
// The first time a point is encountered, the value is recorded and returned, where j=0
if (path[i] == -1) {
path[i] = i;
return i;
} else {
// If I has a record, look backwards for the value at path[i] + 1 and eventually update the path value recursively
path[i] = findPath(path[i] + 1);
return path[i];
}
}
```

For example: A{1, 1, 2, 3, 5, 5, 2, the corresponding path array initializes path values of -1

• 0 Subscript 1 has a path value of -1, updates to 1 after execution and returns 1, where move+=1-1, corresponding to 1 does not require a + 1 operation;
• 1 The path value of subscript 1 is marked as 1, so look backwards for the path value of 1+1. At this time, the path value of 2 found is -1, the value of update path 1 and 2 are both 2 and returned. At last, move+=2-1, 1 needs a + 1 operation.
• 2 Subscript 2 has a path value of 2. Finding a path of 2+1 backwards is worth -1. At this time, update the path values of path 1, 2, 3 to 3. Finally, move+=3-2 requires 1+1 operation for 2.
• 3 Subscript 3 has a path value of 3. Finding a path of 3+1 backwards is worth -1. At this time, update the path values of path 1, 2, 3, 4 to 4. Finally, move+=4-3 requires 1+1 operation for 3.
• 4 Subscript 5 has a path value of -1, updates to 5 after execution and returns 5, where move+=5-5, corresponding to 5 does not require a + 1 operation;
• 5 Subscript 5 has a path value of 5. Finding a path of 5+1 backwards is worth -1. At this time, the path values of path 1, 2, 3, 4, 5, 6 are all updated to 6. The last move+=6-5 requires a + 1 operation for 5.
• 6 Subscript 2 has a path value of 6. Looking backward for a path of 6+1 will result in -1. At this time, the path values of path 1, 2, 3, 4, 5, 6, 7 are updated to 7, and finally move+=7-2, which requires 5 + 1 operations for 2;

The so-called path compression actually records the maximum number of times the current traversal number has passed the + 1 operation, so that the maximum number can be found directly from the path later and the number of times the + 1 is needed is calculated on this basis.

## Sample algorithm source

```package leetcode;

import java.util.Arrays;

/**
* @author ZhouJie
* @date 2020 March 22, 2000 8:04:55 p.m.
* @Description: 945. Minimum increment to make the array unique
*
*/
public class LeetCode_0945 {

}

class Solution_0945 {
/**
* @author: ZhouJie
* @date: 2020 8:08:06 p.m. on March 22, 2000
* @param: @param A
* @param: @return
* @return: int
* @Description: 1-Sort first, then add up the +1 operands needed for each two neighbors from left to right;
* 				Time complexity: O(NlogN) N=A.length
* 				Spatial Complexity: O(1)
*
*/
public int minIncrementForUnique_1(int[] A) {
int len = 0, move = 0;
if (A == null || (len = A.length) < 2) {
return move;
}
Arrays.sort(A);
for (int i = 1; i < len; i++) {
// If the current value is less than or equal to the previous value, the + 1 operation is required, the number of times the + 1 operation is equal to the difference and then + 1, and the current value needs to be updated to the previous value + 1
if (A[i] <= A[i - 1]) {
move += A[i - 1] - A[i] + 1;
A[i] = A[i - 1] + 1;
}
}
return move;
}

/**
* @author: ZhouJie
* @date: 2020 March 22, 2000 8:15:17 p.m.
* @param: @param A
* @param: @return
* @return: int
* @Description: 2-First count and then add up the operands from small to large. The number of times to add up + 1 is -1 of the same number.
* 				In fact, this step of statistics implies sorting (the nature of natural numbers), which is the key reason why it is faster than the 1 method.
* 				Time complexity: O(N) N=max(A.length, max(A))
* 				Spatial Complexity: O(40001) or O(1)
*/
public int minIncrementForUnique_2(int[] A) {
int move = 0;
if (A == null || A.length < 2) {
return move;
}
// Since the maximum is 3999, if + 1 is 40000, 40,000 indexes are required
int[] statistics = new int[40001];
// Maximum number of records used to traverse the right boundary of statistics
int max = 0;
for (int i : A) {
statistics[i]++;
max = Math.max(max, i);
}
max++;
// max is the last possible maximum in A
for (int i = 0; i < max; i++) {
// If the number of statistics[i] in A is greater than 1, it means that the number of statistics[i]-1 needs to be + 1.
// This step is just a + 1 operation for each of the statistics[i]-1 numbers, and the subsequent + 1 is handed over to statistics[i+1] to complete (recursively)
if (statistics[i] > 1) {
move += statistics[i] - 1;
statistics[i + 1] += statistics[i] - 1;
}
}
// If the number of statistics[max] is greater than 1, then statistics[max]-1 (counted as n) requires a + 1 operation;
// This number needs to be + 1 in turn for the number of times 1, 2, 3, 4....n, that is, to sum 1-n, directly using the summation formula
if (statistics[max] > 1) {
int n = statistics[max] - 1;
move += n * (n + 1) / 2;
}
return move;
}

/**
* @author: ZhouJie
* @date: 2020 March 22, 2000 8:36:13 p.m.
* @param: @param A
* @param: @return
* @return: int
* @Description: 1-Path compression; (from the LeetCode review area, nice...)
* 				Time complexity: O(N) N=A.length
* 				Spatial Complexity: O(80000) or O(1)
* 				Since findPath can change values for multiple points at a time, it is not as efficient as Method 2.
*/

// If all numbers in A are equal and 39999, the maximum value will be 79999 when the + 1 operation is completed
int[] path = new int[80000];

public int minIncrementForUnique_3(int[] A) {
int move = 0;
if (A == null || A.length < 2) {
return move;
}
// -1 is an empty address mark, different from the median of A
Arrays.fill(path, -1);
for (int i : A) {
int j = findPath(i);
move += j - i;
}
return move;
}

/**
* @author: ZhouJie
* @date: 2020 March 22, 2000 8:49:55 p.m.
* @param: @param i
* @param: @return
* @return: int
* @Description: Path Compression Core
*
*/
private int findPath(int i) {
// The first time a point is encountered, the value is recorded and returned, where j=0
if (path[i] == -1) {
path[i] = i;
return i;
} else {
// If I has a record, look backwards for the value at path[i] + 1 and eventually update the path value recursively
path[i] = findPath(path[i] + 1);
return path[i];
}
}
}

```

Posted by tomato on Sun, 22 Mar 2020 10:52:55 -0700