-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path1187-Make_Array_Strictly_Increasing.java
More file actions
142 lines (131 loc) · 4.36 KB
/
1187-Make_Array_Strictly_Increasing.java
File metadata and controls
142 lines (131 loc) · 4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*******************************************************************************
* 1187-Make_Array_Strictly_Increasing.java
* Billy.Ljm
* 17 June 2023
*
* =======
* Problem
* =======
* https://leetcode.com/problems/make-array-strictly-increasing/
*
* Given two integer arrays arr1 and arr2, return the minimum number of
* operations (possibly zero) needed to make arr1 strictly increasing.
*
* In one operation, you can choose two indices 0 <= i < arr1.length and
* 0 <= j < arr2.length and do the assignment arr1[i] = arr2[j].
*
* If there is no way to make arr1 strictly increasing, return -1.
*
* ===========
* My Approach
* ===========
* At each element of arr1, we either (1) leave the element alone, or (2) replace
* it with the smallest element in arr2 that is larger than the previous element
* of arr1. We can then simulate all strategies recursively, with memoisation to
* avoid repeated work.
*
* This would have a time complexity of O(n log n + n * m) and space complexity
* of O(n*m) where n is the length of arr1 and m is the length of arr2.
******************************************************************************/
import java.util.Arrays;
import java.util.HashMap;
import java.lang.String;
class Solution {
private int [] arr1, arr2; // input arrays, to pass to helper function
private HashMap<String, Integer> memo; // memoise recurse()
/**
* Recursively consider swap or don't swap each element of arr1
*
* @param i current element being operated on
* @param prev value of previous element
* @param i2 index of smallest element in arr2 that is larger than prev
* @return minimum number of operations needed to make arr1 strictly increasing
*/
private int recurse(int i, int prev, int i2) {
// if arr1 increasing, return
if (i >= arr1.length) return 0;
// if memoised, return
else if (memo.containsKey(i + "," + prev)) {
return memo.get(i + "," + prev);
}
// find next element in arr2 that is larger than prev
while(i2 < arr2.length && arr2[i2] <= prev) i2++;
// if arr2 exhausted
if (i2 >= arr2.length) {
// return INT_MAX if arr1 not increasing
while (i < arr1.length) {
if (arr1[i] <= prev) {
memo.put(i + "," + prev, -1);
return -1;
}
prev = arr1[i];
i++;
}
// return 0 of arr1 already increasing
memo.put(i + "," + prev, 0);
return 0;
}
// else recursively consider all options
else {
int nmoves;
// if must swap
if (arr1[i] <= prev) {
nmoves = recurse(i + 1, arr2[i2], i2);
if (nmoves != -1) nmoves++; // current swap move
}
// else consider both cases
else {
// recurse
int noswap = recurse(i + 1, arr1[i], i2);
int swap = recurse(i + 1, arr2[i2], i2);
if (swap != -1) swap++; // current sawp move
// handle -1 cases, answer will be saved in noswap
if (noswap == -1 && swap == -1) nmoves = -1;
else if (noswap == -1) nmoves = swap;
else if (swap == -1) nmoves = noswap;
else nmoves = Math.min(noswap, swap);
}
// memoise
memo.put(i + "," + prev, nmoves);
return nmoves;
}
}
/**
* Finds the minimum number of replacements of elements in arr1 with that of
* arr2 to make arr1 strictly increasing
* @param arr1 array to make strictly increasing
* @param arr2 array of values that be used to replace elements in arr1
* @return minimum number of replacements to make arr1 strictly increasing
*/
public int makeArrayIncreasing(int[] arr1, int[] arr2) {
Arrays.sort(arr2);
this.arr1 = arr1;
this.arr2 = arr2;
this.memo = new HashMap<String, Integer>();
return recurse(0, -1, 0);
}
}
class Test {
/**
* Test cases
*/
public static void main(String[] args) {
Solution sol = new Solution();
int[] arr1, arr2;
// test case 1
arr1 = new int[] {1,5,3,6,7};
arr2 = new int[] {1,3,2,4};
System.out.println("makeArrayIncreasing(" + Arrays.toString(arr1) + ","
+ Arrays.toString(arr2) + ") = " + sol.makeArrayIncreasing(arr1, arr2));
// test case 2
arr1 = new int[] {1,5,3,6,7};
arr2 = new int[] {4,3,1};
System.out.println("makeArrayIncreasing(" + Arrays.toString(arr1) + ","
+ Arrays.toString(arr2) + ") = " + sol.makeArrayIncreasing(arr1, arr2));
// test case 3
arr1 = new int[] {1,5,3,6,7};
arr2 = new int[] {1,6,3,3};
System.out.println("makeArrayIncreasing(" + Arrays.toString(arr1) + ","
+ Arrays.toString(arr2) + ") = " + sol.makeArrayIncreasing(arr1, arr2));
}
}