- 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
- 55 lines of Java from the credited upstream file 3116.java.
- The implementation visibly relies on sequence storage.
- 6 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 long findKthSmallest(int[] coins, int k) {3 List<Long>[] sizeToLcms = getSizeToLcms(coins);4 long l = 0;5 long r = (long) k * Arrays.stream(coins).min().getAsInt();6 7 while (l < r) {8 final long m = (l + r) / 2;9 if (numDenominationsNoGreaterThan(sizeToLcms, m) >= k)10 r = m;11 else12 l = m + 1;13 }14 15 return l;16 }17 18 19 private long numDenominationsNoGreaterThan(List<Long>[] sizeToLcms, long m) {20 long res = 0;21 for (int sz = 1; sz < sizeToLcms.length; ++sz)22 for (long lcm : sizeToLcms[sz])23 res += m / lcm * Math.pow(-1, sz + 1);24 return res;25 }26 27 28 private List<Long>[] getSizeToLcms(int[] coins) {29 final int n = coins.length;30 final int maxMask = 1 << n;31 List<Long>[] sizeToLcms = new List[n + 1];32 33 for (int i = 1; i <= n; ++i)34 sizeToLcms[i] = new ArrayList<>();35 36 for (int mask = 1; mask < maxMask; ++mask) {37 long lcmOfSelectedCoins = 1;38 for (int i = 0; i < n; ++i)39 if ((mask >> i & 1) == 1)40 lcmOfSelectedCoins = lcm(lcmOfSelectedCoins, coins[i]);41 sizeToLcms[Integer.bitCount(mask)].add(lcmOfSelectedCoins);42 }43 44 return sizeToLcms;45 }46 47 private long lcm(long a, long b) {48 return a * b / gcd(a, b);49 }50 51 private long gcd(long a, long b) {52 return b == 0 ? a : gcd(b, a % b);53 }54}55