- Choose the invariant that makes a window valid or useful.
- Advance the right boundary and add the new element.
- Move the left boundary only as needed while maintaining the invariant and updating the answer.
Code notes
- 98 lines of Java from the credited upstream file 2818.java.
- The implementation visibly relies on sequence storage, hash lookup, ordered lookup, work queue.
- 12 loop blocks detected.
Complexity
Confirm that neither pointer moves backwards; if so, the scan is usually linear apart from the window’s data-structure operations.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
1class Solution {2 public int maximumScore(List<Integer> nums, int k) {3 final int n = nums.size();4 final int mx = Collections.max(nums);5 final int[] minPrimeFactors = sieveEratosthenes(mx + 1);6 final int[] primeScores = getPrimeScores(nums, minPrimeFactors);7 int ans = 1;8 9 10 int[] left = new int[n];11 Arrays.fill(left, -1);12 13 14 int[] right = new int[n];15 Arrays.fill(right, n);16 Deque<Integer> stack = new ArrayDeque<>();17 18 19 for (int i = n - 1; i >= 0; --i) {20 while (!stack.isEmpty() && primeScores[stack.peek()] <= primeScores[i])21 left[stack.pop()] = i;22 stack.push(i);23 }24 25 stack.clear();26 27 28 for (int i = 0; i < n; ++i) {29 while (!stack.isEmpty() && primeScores[stack.peek()] < primeScores[i])30 right[stack.pop()] = i;31 stack.push(i);32 }33 34 Pair<Integer, Integer>[] numAndIndexes = new Pair[n];35 36 for (int i = 0; i < n; ++i)37 numAndIndexes[i] = new Pair<>(nums.get(i), i);38 39 Arrays.sort(numAndIndexes,40 Comparator.comparing(Pair<Integer, Integer>::getKey, Comparator.reverseOrder())41 .thenComparingInt(Pair<Integer, Integer>::getValue));42 43 for (Pair<Integer, Integer> numAndIndex : numAndIndexes) {44 final int num = numAndIndex.getKey();45 final int i = numAndIndex.getValue();46 47 48 49 final long rangeCount = (long) (i - left[i]) * (right[i] - i);50 final long actualCount = Math.min(rangeCount, (long) k);51 k -= actualCount;52 ans = (int) ((1L * ans * modPow(num, actualCount)) % MOD);53 }54 55 return ans;56 }57 58 private static final int MOD = 1_000_000_007;59 60 private long modPow(long x, long n) {61 if (n == 0)62 return 1;63 if (n % 2 == 1)64 return x * modPow(x, n - 1) % MOD;65 return modPow(x * x % MOD, n / 2);66 }67 68 69 private int[] sieveEratosthenes(int n) {70 int[] minPrimeFactors = new int[n + 1];71 for (int i = 2; i <= n; ++i)72 minPrimeFactors[i] = i;73 for (int i = 2; i * i < n; ++i)74 if (minPrimeFactors[i] == i) 75 for (int j = i * i; j < n; j += i)76 minPrimeFactors[j] = Math.min(minPrimeFactors[j], i);77 return minPrimeFactors;78 }79 80 private int[] getPrimeScores(List<Integer> nums, int[] minPrimeFactors) {81 int[] primeScores = new int[nums.size()];82 for (int i = 0; i < nums.size(); ++i)83 primeScores[i] = getPrimeScore(nums.get(i), minPrimeFactors);84 return primeScores;85 }86 87 private int getPrimeScore(int num, int[] minPrimeFactors) {88 Set<Integer> primeFactors = new HashSet<>();89 while (num > 1) {90 final int divisor = minPrimeFactors[num];91 primeFactors.add(divisor);92 while (num % divisor == 0)93 num /= divisor;94 }95 return primeFactors.size();96 }97}98