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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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));
}
}