diff --git a/src/main/java/g1801_1900/s1815_maximum_number_of_groups_getting_fresh_donuts/Solution.java b/src/main/java/g1801_1900/s1815_maximum_number_of_groups_getting_fresh_donuts/Solution.java index 8060c27df..adf572e28 100644 --- a/src/main/java/g1801_1900/s1815_maximum_number_of_groups_getting_fresh_donuts/Solution.java +++ b/src/main/java/g1801_1900/s1815_maximum_number_of_groups_getting_fresh_donuts/Solution.java @@ -1,60 +1,89 @@ package g1801_1900.s1815_maximum_number_of_groups_getting_fresh_donuts; // #Hard #Array #Dynamic_Programming #Bit_Manipulation #Bitmask #Memoization -// #2022_05_03_Time_7_ms_(86.67%)_Space_43.6_MB_(73.33%) +// #2025_02_21_Time_2_ms_(100.00%)_Space_41.56_MB_(100.00%) -import java.util.Arrays; import java.util.HashMap; import java.util.Map; public class Solution { - private static final Map MAP = new HashMap<>(); - public int maxHappyGroups(int batchSize, int[] groups) { - int[] count = new int[batchSize]; - int res = 0; - int remGroup = 0; - for (int group : groups) { - int g = group % batchSize; - if (g == 0) { - res++; - } else if (count[batchSize - g] > 0) { - remGroup--; - res++; - count[batchSize - g]--; - } else { - count[g]++; - remGroup++; - } + if (batchSize == 1) { + return groups.length; + } + int[] withSize = new int[batchSize]; + for (int size : groups) { + withSize[size % batchSize]++; + } + int fromZero = withSize[0]; + withSize[0] = 0; + int fromEnds = 0; + for (int l = 1, r = batchSize - 1; l < r; l++, r--) { + int usable = Math.min(withSize[l], withSize[r]); + fromEnds += usable; + withSize[l] -= usable; + withSize[r] -= usable; } - res += dfs(0, remGroup, count, batchSize); - return res; + int fromMid = 0; + if (batchSize % 2 == 0) { + fromMid = withSize[batchSize / 2] / 2; + withSize[batchSize / 2] -= fromMid * 2; + } + return get(pruneEnd(withSize), batchSize, 0, new HashMap<>()) + + fromZero + + fromEnds + + fromMid; } - private int dfs(int curr, int remain, int[] count, int batch) { - if (remain == 0) { - return 0; + private int get(int[] ar, int batchSize, int rem, Map cache) { + long hash = 0; + for (int e : ar) { + hash = hash * 69L + e; } - int res = 0; - String s = Arrays.toString(count); - if (MAP.containsKey(s)) { - return MAP.get(s); + Integer fromCache = cache.get(hash); + if (fromCache != null) { + return fromCache; } - if (curr == 0) { - res++; - curr = batch; + if (zeroed(ar)) { + cache.put(hash, 0); + return 0; } - int val = 0; - for (int i = 1; i < count.length; i++) { - if (count[i] == 0) { + int max = 0; + for (int i = 0; i < ar.length; i++) { + if (ar[i] == 0) { continue; } - count[i]--; - val = Math.max(val, dfs((curr - i + batch) % batch, remain - 1, count, batch)); - count[i]++; + ar[i]--; + int from = get(ar, batchSize, (rem + i) % batchSize, cache); + if (from > max) { + max = from; + } + ar[i]++; + } + int score = max + (rem == 0 ? 1 : 0); + cache.put(hash, score); + return score; + } + + private int[] pruneEnd(int[] in) { + int endingZeros = 0; + for (int i = in.length - 1; i >= 0; i--) { + if (in[i] != 0) { + break; + } + endingZeros++; + } + int[] out = new int[in.length - endingZeros]; + System.arraycopy(in, 0, out, 0, out.length); + return out; + } + + private boolean zeroed(int[] ar) { + for (int e : ar) { + if (e != 0) { + return false; + } } - res += val; - MAP.put(s, res); - return res; + return true; } } diff --git a/src/test/java/g1801_1900/s1815_maximum_number_of_groups_getting_fresh_donuts/SolutionTest.java b/src/test/java/g1801_1900/s1815_maximum_number_of_groups_getting_fresh_donuts/SolutionTest.java index 2c140d800..7bd950983 100644 --- a/src/test/java/g1801_1900/s1815_maximum_number_of_groups_getting_fresh_donuts/SolutionTest.java +++ b/src/test/java/g1801_1900/s1815_maximum_number_of_groups_getting_fresh_donuts/SolutionTest.java @@ -16,4 +16,36 @@ void maxHappyGroups2() { assertThat( new Solution().maxHappyGroups(4, new int[] {1, 3, 2, 5, 2, 2, 1, 6}), equalTo(4)); } + + @Test + void maxHappyGroups3() { + assertThat( + new Solution() + .maxHappyGroups( + 7, + new int[] { + 287773481, 815094798, 356732984, 644469322, 543193620, + 903158817, 274116865, 395252956, 363839119, 365378492, + 122313059, 312690039, 252532812 + }), + equalTo(9)); + } + + @Test + void maxHappyGroups4() { + assertThat( + new Solution() + .maxHappyGroups( + 9, + new int[] { + 3, 1, 3, 3, 5, 6, 1, 1, 9, 10, 3, 3, 3, 1, 1, 3, 3, 3, 19, 20, + 1, 3, 3, 3, 3, 1, 1, 3, 3, 30 + }), + equalTo(9)); + } + + @Test + void maxHappyGroups5() { + assertThat(new Solution().maxHappyGroups(1, new int[] {1, 2, 3}), equalTo(3)); + } }