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