diff --git a/leetcode_java/src/main/java/LeetCodeJava/HashTable/ContinuousSubarraySum.java b/leetcode_java/src/main/java/LeetCodeJava/HashTable/ContinuousSubarraySum.java index 7867f54f..fdf13d7b 100644 --- a/leetcode_java/src/main/java/LeetCodeJava/HashTable/ContinuousSubarraySum.java +++ b/leetcode_java/src/main/java/LeetCodeJava/HashTable/ContinuousSubarraySum.java @@ -128,7 +128,7 @@ public boolean checkSubarraySum_0_1(int[] nums, int k) { * * -> idea 1) (presum + cur) % k - (presum) = 0, so it's k multiple * - * + * */ presum = (presum + cur) % k; // NOTE !!! below diff --git a/leetcode_java/src/main/java/LeetCodeJava/HashTable/SubarraySumEqualsK.java b/leetcode_java/src/main/java/LeetCodeJava/HashTable/SubarraySumEqualsK.java index 0ea9fbc8..8cedb47a 100644 --- a/leetcode_java/src/main/java/LeetCodeJava/HashTable/SubarraySumEqualsK.java +++ b/leetcode_java/src/main/java/LeetCodeJava/HashTable/SubarraySumEqualsK.java @@ -85,6 +85,22 @@ public int subarraySum(int[] nums, int k) { * NOTE !!! * * Initialize the map with prefix sum 0 (to handle subarrays starting at index 0) + * + * + * + * Purpose of map.put(0, 1); + * + * 1. Handle the Initial Case: + * • The prefix sum presum starts at 0 before any elements of the array are processed. + * • Adding map.put(0, 1) ensures that if a subarray’s prefix sum equals k (e.g., the subarray itself equals k ), it is counted correctly. + * + * 2. Account for Subarrays Starting at Index 0: + * • Consider the case where the cumulative sum of elements up to a certain index j equals k : presum[j] = k + * • The subarray from index 0 to j should count as a valid subarray. + * • To check this condition, the code calculates presum - k and looks for it in the map. For subarrays starting at index 0, presum - k equals 0. Adding map.put(0, 1) ensures this case is handled properly. + * + * 3. Count Prefix Sums: + * • The value 1 in map.put(0, 1) represents the fact that there is one prefix sum of 0 initially (before processing any elements). This allows the algorithm to correctly count subarrays that sum to k as the prefix sum progresses. */ map.put(0, 1); @@ -103,6 +119,58 @@ public int subarraySum(int[] nums, int k) { return count; } + // V0-1 + // IDEA : HASH MAP (fixed by gpt) + public int subarraySum_0_1(int[] nums, int k) { + + if (nums.length == 1){ + if (nums[0] == k){ + return 1; + } + return 0; + } + + // map : {presum : count} + Map map = new HashMap<>(); + /** NOTE !!! + * + * init map as below + * + * Initialize the map with prefix sum 0 (to handle subarrays starting at index 0) + */ + map.put(0,1); + int preusm = 0; + int cnt = 0; + for (int i = 0; i < nums.length; i++){ + int cur = nums[i]; + preusm += cur; + /** + * Reason why update map after `count` update (e.g. map.put(preusm, map.getOrDefault(preusm, 0) + 1) after if condition) + * + * 1. Avoid Overcounting: + * • When checking if (map.containsKey(preusm - k)), you are looking for how many previous subarrays have a prefix sum of preusm - k. + * • If you update the map before this check (i.e., increment the count for the current preusm), you might mistakenly count the current subarray itself in this operation, leading to incorrect results. + * + * 2. Logical Order of Operations: + * • The purpose of the map is to store the counts of previous prefix sums seen so far. + * • When you calculate cnt += map.get(preusm - k), you are determining how many times the subarray sum k has been encountered up to this point. + * • Only after this check should you update the map to include the current preusm for subsequent iterations. + * + * 3. Current Subarray Shouldn’t Influence Itself: + * • In the current iteration, the subarray being evaluated shouldn’t count itself as contributing to the result. By updating the map after the check, you ensure the current prefix sum becomes available only for future iterations. + * + */ + //map.put(preusm, map.getOrDefault(preusm, 0) + 1); + if (map.containsKey(preusm - k)){ + cnt += map.get(preusm - k); + } + // NOTE !! update map after `if condition` + map.put(preusm, map.getOrDefault(preusm, 0) + 1); + } + + return cnt; + } + // V1 // IDEA : HASH MAP // https://leetcode.com/problems/subarray-sum-equals-k/solutions/6143642/java-beats-9983-by-mohamedhazem3-9yj6/ diff --git a/leetcode_java/src/main/java/dev/workspace5.java b/leetcode_java/src/main/java/dev/workspace5.java index 8b338c0e..4db642b2 100644 --- a/leetcode_java/src/main/java/dev/workspace5.java +++ b/leetcode_java/src/main/java/dev/workspace5.java @@ -4516,34 +4516,83 @@ public boolean checkSubarraySum(int[] nums, int k) { */ public int subarraySum(int[] nums, int k) { - if(nums.length==1){ - return nums[0] == k ? 1 : 0; + if (nums.length == 1){ + if (nums[0] == k){ + return 1; + } + return 0; } - // map : {presum : idx} + // map : {presum : count} Map map = new HashMap<>(); - int presum = 0; + /** NOTE !!! + * + * init map as below + */ + map.put(0,1); // TODO : check + int preusm = 0; int cnt = 0; - map.put(0, -1); // TODO : check if necessary for (int i = 0; i < nums.length; i++){ int cur = nums[i]; - presum += cur; - map.putIfAbsent(presum, i); // ??? + preusm += cur; /** - * sum(i,j) = presum(j+1) - presum(i) + * Reason why update map after `count` update (e.g. map.put(preusm, map.getOrDefault(preusm, 0) + 1) after if condition) + * + * 1. Avoid Overcounting: + * • When checking if (map.containsKey(preusm - k)), you are looking for how many previous subarrays have a prefix sum of preusm - k. + * • If you update the map before this check (i.e., increment the count for the current preusm), you might mistakenly count the current subarray itself in this operation, leading to incorrect results. + * + * 2. Logical Order of Operations: + * • The purpose of the map is to store the counts of previous prefix sums seen so far. + * • When you calculate cnt += map.get(preusm - k), you are determining how many times the subarray sum k has been encountered up to this point. + * • Only after this check should you update the map to include the current preusm for subsequent iterations. + * + * 3. Current Subarray Shouldn’t Influence Itself: + * • In the current iteration, the subarray being evaluated shouldn’t count itself as contributing to the result. By updating the map after the check, you ensure the current prefix sum becomes available only for future iterations. * - * k = presum(j+1) - presum(i) - * -> presum(i) = presum(j+1) - k */ - if (map.containsKey(presum - k) && map.get(presum - k) == i+1){ - cnt += 1; + //map.put(preusm, map.getOrDefault(preusm, 0) + 1); + if (map.containsKey(preusm - k)){ + cnt += map.get(preusm - k); } - //map.putIfAbsent(presum, i); + // NOTE !! update map after `if condition` + map.put(preusm, map.getOrDefault(preusm, 0) + 1); } return cnt; } + +// public int subarraySum(int[] nums, int k) { +// +// if(nums.length==1){ +// return nums[0] == k ? 1 : 0; +// } +// +// // map : {presum : idx} +// Map map = new HashMap<>(); +// int presum = 0; +// int cnt = 0; +// map.put(0, -1); // TODO : check if necessary +// for (int i = 0; i < nums.length; i++){ +// int cur = nums[i]; +// presum += cur; +// map.putIfAbsent(presum, i); // ??? +// /** +// * sum(i,j) = presum(j+1) - presum(i) +// * +// * k = presum(j+1) - presum(i) +// * -> presum(i) = presum(j+1) - k +// */ +// if (map.containsKey(presum - k) && map.get(presum - k) == i+1){ +// cnt += 1; +// } +// //map.putIfAbsent(presum, i); +// } +// +// return cnt; +// } + // LC 1109 // https://leetcode.com/problems/corporate-flight-bookings/ public int[] corpFlightBookings(int[][] bookings, int n) {