You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

146 lines
3.3 KiB

2 years ago
package class04;
// 测试链接 : https://leetcode.com/problems/candy/
public class Code05_CandyProblem {
// 这是原问题的优良解
// 时间复杂度O(N)额外空间复杂度O(N)
public static int candy1(int[] arr) {
if (arr == null || arr.length == 0) {
return 0;
}
int N = arr.length;
int[] left = new int[N];
for (int i = 1; i < N; i++) {
if (arr[i - 1] < arr[i]) {
left[i] = left[i - 1] + 1;
}
}
int[] right = new int[N];
for (int i = N - 2; i >= 0; i--) {
if (arr[i] > arr[i + 1]) {
right[i] = right[i + 1] + 1;
}
}
int ans = 0;
for (int i = 0; i < N; i++) {
ans += Math.max(left[i], right[i]);
}
return ans + N;
}
// 这是原问题空间优化后的解
// 时间复杂度O(N)额外空间复杂度O(1)
public static int candy2(int[] arr) {
if (arr == null || arr.length == 0) {
return 0;
}
int index = nextMinIndex2(arr, 0);
int res = rightCands(arr, 0, index++);
int lbase = 1;
int next = 0;
int rcands = 0;
int rbase = 0;
while (index != arr.length) {
if (arr[index] > arr[index - 1]) {
res += ++lbase;
index++;
} else if (arr[index] < arr[index - 1]) {
next = nextMinIndex2(arr, index - 1);
rcands = rightCands(arr, index - 1, next++);
rbase = next - index + 1;
res += rcands + (rbase > lbase ? -lbase : -rbase);
lbase = 1;
index = next;
} else {
res += 1;
lbase = 1;
index++;
}
}
return res;
}
public static int nextMinIndex2(int[] arr, int start) {
for (int i = start; i != arr.length - 1; i++) {
if (arr[i] <= arr[i + 1]) {
return i;
}
}
return arr.length - 1;
}
public static int rightCands(int[] arr, int left, int right) {
int n = right - left + 1;
return n + n * (n - 1) / 2;
}
// 这是进阶问题的最优解,不要提交这个
// 时间复杂度O(N), 额外空间复杂度O(1)
public static int candy3(int[] arr) {
if (arr == null || arr.length == 0) {
return 0;
}
int index = nextMinIndex3(arr, 0);
int[] data = rightCandsAndBase(arr, 0, index++);
int res = data[0];
int lbase = 1;
int same = 1;
int next = 0;
while (index != arr.length) {
if (arr[index] > arr[index - 1]) {
res += ++lbase;
same = 1;
index++;
} else if (arr[index] < arr[index - 1]) {
next = nextMinIndex3(arr, index - 1);
data = rightCandsAndBase(arr, index - 1, next++);
if (data[1] <= lbase) {
res += data[0] - data[1];
} else {
res += -lbase * same + data[0] - data[1] + data[1] * same;
}
index = next;
lbase = 1;
same = 1;
} else {
res += lbase;
same++;
index++;
}
}
return res;
}
public static int nextMinIndex3(int[] arr, int start) {
for (int i = start; i != arr.length - 1; i++) {
if (arr[i] < arr[i + 1]) {
return i;
}
}
return arr.length - 1;
}
public static int[] rightCandsAndBase(int[] arr, int left, int right) {
int base = 1;
int cands = 1;
for (int i = right - 1; i >= left; i--) {
if (arr[i] == arr[i + 1]) {
cands += base;
} else {
cands += ++base;
}
}
return new int[] { cands, base };
}
public static void main(String[] args) {
int[] test1 = { 3, 0, 5, 5, 4, 4, 0 };
System.out.println(candy2(test1));
int[] test2 = { 3, 0, 5, 5, 4, 4, 0 };
System.out.println(candy3(test2));
}
}