Skip to content

Commit f2fc981

Browse files
committed
leetcode
1 parent 042f9e2 commit f2fc981

File tree

4 files changed

+300
-0
lines changed

4 files changed

+300
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ This repo contain leetcode solution using DART and GO programming language. Most
188188
- [**57.** Insert Interval](InsertInterval/insert_interval.dart)
189189
- [**926.** Flip String to Monotone Increasing](FlipStringToMonotoneIncreasing/flip_string_to_monotone_increasing.dart)
190190
- [**918.** Maximum Sum Circular Sub-Array](MaximumSumCircularSubarray/maximum_sum_circular_subarray.dart)
191+
- [**974.** SubArray Sums Divisible by K](SubarraySumsDivisibleByK/subarray_sums_divisible_by_k.dart)
191192

192193
## Reach me via
193194

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
3+
-* 974. Sub-array Sums Divisible by K *-
4+
5+
6+
Given an integer array nums and an integer k, return the number of non-empty subarrays that have a sum divisible by k.
7+
8+
A subarray is a contiguous part of an array.
9+
10+
11+
12+
Example 1:
13+
14+
Input: nums = [4,5,0,-2,-3,1], k = 5
15+
Output: 7
16+
Explanation: There are 7 subarrays with a sum divisible by k = 5:
17+
[4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3]
18+
Example 2:
19+
20+
Input: nums = [5], k = 9
21+
Output: 0
22+
23+
24+
Constraints:
25+
26+
1 <= nums.length <= 3 * 104
27+
-104 <= nums[i] <= 104
28+
2 <= k <= 104
29+
30+
*/
31+
32+
import 'dart:collection';
33+
34+
class A {
35+
int subarraysDivByK(List<int> nums, int k) {
36+
// Use the HashMap to record the frequency of all the prefix sum remainders.
37+
HashMap<int, int> map = HashMap();
38+
// Note that the integer in 'nums' can be negative.
39+
// Thus, we need to adjust the negative remainder to positive remainder.
40+
// Below accounts for both negative and positive remainders.
41+
// We can also check if the remainder is negative, then add a 'k' to make the remainder positive.
42+
// For Example, nums = [-2,3,2], k = 5,
43+
// remainder for the prefix sum of [-2,1,3] are -2, 1 and 3 respectively.
44+
// We know that [3,2] sum to 5, which is divisible by 5.
45+
// After converting -2 to 3, by adding 5, it has the same remainder with prefix sum 3.
46+
for (int i = 0, remainder; i < nums.length; i++) {
47+
if (i > 0) nums[i] += nums[i - 1];
48+
remainder = (nums[i] % k + k) % k;
49+
map[remainder] = (map[remainder] ?? 0) + 1;
50+
}
51+
// The result contains all the prefix sum with remainder 0,
52+
// as all the prefix sum with remainder of 0 is itself divisible by 'k'.
53+
// However, do note that the prefix sum with remainder 0 also able to form sub-array sums that is divisible by 'k'
54+
// with one another, which will be calculated next.
55+
// For Example: nums = [5,5,5,5], k = 5,
56+
// The prefix sum of [5,10,15,20] are themselves divisible by 5, while also forming sub-array sums divisible by 5
57+
// with 10 [5,5] - 5 [5] == 5, 15 [5,5,5] - 5 [5] == 10, etc.
58+
int result = (map[0] ?? 0);
59+
// The prefix sums with the same remainder can form sub-array sums that is divisible by 'k' with each other.
60+
// For each remainder, the number of sub-array that is divisible by 'k' is the number of combinations from the frequency.
61+
// Equation for the number of combinations of n items is n * "(n - 1) / 2".
62+
for (int frequency in map.values)
63+
result += frequency * (frequency - 1) ~/ 2;
64+
return result;
65+
}
66+
}
67+
68+
class B {
69+
int subarraysDivByK(List<int> nums, int k) {
70+
// Use counting array to record the frequency of all the prefix sum remainders.
71+
List<int> counting = List.filled(k, 0);
72+
for (int i = 0; i < nums.length; i++) {
73+
if (i > 0) nums[i] += nums[i - 1];
74+
// Note that the integer in 'nums' can be negative.
75+
// Thus, we need to adjust the negative remainder to positive remainder.
76+
// Below accounts for both negative and positive remainders.
77+
// We can also check if the remainder is negative, then add a 'k' to make the remainder positive.
78+
// For Example, nums = [-2,3,2], k = 5,
79+
// remainder for the prefix sum of [-2,1,3] are -2, 1 and 3 respectively.
80+
// We know that [3,2] sum to 5, which is divisible by 5.
81+
// After converting -2 to 3, by adding 5, it has the same remainder with prefix sum 3.
82+
counting[(nums[i] % k + k) % k]++;
83+
}
84+
85+
// The result contains all the prefix sum with remainder 0,
86+
// as all the prefix sum with remainder of 0 is itself divisible by 'k'.
87+
// However, do note that the prefix sum with remainder 0 also able to form subarray sums that is divisible by 'k'
88+
// with one another, which will be calculated next.
89+
// For Example: nums = [5,5,5,5], k = 5,
90+
// The prefix sum of [5,10,15,20] are themselves divisible by 5, while also forming subarray sums divisible by 5
91+
// with 10 [5,5] - 5 [5] == 5, 15 [5,5,5] - 5 [5] == 10, etc.
92+
int result = counting[0];
93+
94+
// The prefix sums with the same remainder can form subarray sums that is divisible by 'k' with each other.
95+
// For each remainder, the number of subarray that is divisible by 'k' is the number of combinations from the frequency.
96+
// Equation for the number of combinations of n items is n * "(n - 1) / 2".
97+
for (int frequency in counting) result += frequency * (frequency - 1) ~/ 2;
98+
99+
return result;
100+
}
101+
}
102+
103+
class C {
104+
int subarraysDivByK(List<int> nums, int k) {
105+
int sum = 0;
106+
int cnt = 0;
107+
HashMap<int, int> hm = HashMap();
108+
hm[0] = 1;
109+
for (int i = 0; i < nums.length; i++) {
110+
sum += nums[i];
111+
112+
int diff = sum % k;
113+
114+
if (diff < 0) {
115+
diff += k;
116+
}
117+
118+
if (hm.containsKey(diff)) {
119+
cnt += hm[diff]!;
120+
}
121+
hm[diff] = (hm[diff] ?? 0) + 1;
122+
}
123+
return cnt;
124+
}
125+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package main
2+
3+
func subarraysDivByK(nums []int, k int) int {
4+
var mp map[int]int = make(map[int]int)
5+
var ans int
6+
var sum int
7+
for i := 0; i < len(nums); i++ {
8+
sum = (sum + nums[i]) % k
9+
if sum < 0 {
10+
sum = (sum + k) % k
11+
}
12+
if sum == 0 {
13+
ans++
14+
}
15+
if mp[sum] != 0 {
16+
ans += mp[sum]
17+
mp[sum]++
18+
} else {
19+
mp[sum] = 1
20+
}
21+
}
22+
return ans
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# 🔥 3 FAST Approaches 🔥 || Simple Fast and Easy || with Explanation
2+
3+
## Approach
4+
5+
When it comes to Sum of Sub-array, the use of Prefix Sum is especially important.
6+
7+
Prefix Sum is the sum of the current integer with the previous integer in the array (Prefix).
8+
9+
Example: nums = [1,2,3,4,5] has the prefix sum array of prefixSum = [1,3,6,10,15], where the nums[0] + 1 = 1, nums[1] + nums[0] = 2 + 1 = 3, nums[2] + nums[1] = 3 + 3 = 6, and so on.
10+
11+
Using the example above, we can determine the sub-array sum of any sub-array using prefix sum.
12+
13+
To get the sub-array sum of nums[2] to nums[4] == 3 + 4 + 5 == 12, we can get from prefixSum[5] - prefixSum[1] == 15 - 3 == 12.
14+
15+
With Prefix Sum, we can evaluate if any sub-array sum is divisible by 'k', if two prefix sums have the same remainder of 'k'.
16+
17+
For Example, nums = [4,2,3], k = 5, with two prefix sum, 4 [4] and 9 [4,2,3].
18+
19+
Both remainders are 4, with the sub-array between the prefix sum 9 [4,2,3] - 4 [4] == 5 [2,3], which is divisible by 5.
20+
21+
Prefix Sum & Hash Table
22+
23+
## Complexity
24+
25+
### Time Complexity: O(n)
26+
27+
where 'n' is the length of 'nums'.
28+
In fact, in actual is '2n' as we traverse 'nums' once and the HashMap once, with the worst time complexity of the HashMap being 'n'.
29+
30+
### Space Complexity: O(n)
31+
32+
where 'n' is the length of 'nums'.
33+
The worst case is when all the prefix sums in 'nums' have different remainders with 'k', resulting in the maximum size of the HashMap to be 'n'.
34+
35+
## Code
36+
37+
```dart
38+
class Solution {
39+
int subarraysDivByK(List<int> nums, int k) {
40+
// Use the HashMap to record the frequency of all the prefix sum remainders.
41+
HashMap<int, int> map = HashMap();
42+
// Note that the integer in 'nums' can be negative.
43+
// Thus, we need to adjust the negative remainder to positive remainder.
44+
// Below accounts for both negative and positive remainders.
45+
// We can also check if the remainder is negative, then add a 'k' to make the remainder positive.
46+
// For Example, nums = [-2,3,2], k = 5,
47+
// remainder for the prefix sum of [-2,1,3] are -2, 1 and 3 respectively.
48+
// We know that [3,2] sum to 5, which is divisible by 5.
49+
// After converting -2 to 3, by adding 5, it has the same remainder with prefix sum 3.
50+
for (int i = 0, remainder; i < nums.length; i++) {
51+
if (i > 0) nums[i] += nums[i - 1];
52+
remainder = (nums[i] % k + k) % k;
53+
map[remainder] = (map[remainder] ?? 0) + 1;
54+
}
55+
// The result contains all the prefix sum with remainder 0,
56+
// as all the prefix sum with remainder of 0 is itself divisible by 'k'.
57+
// However, do note that the prefix sum with remainder 0 also able to form sub-array sums that is divisible by 'k'
58+
// with one another, which will be calculated next.
59+
// For Example: nums = [5,5,5,5], k = 5,
60+
// The prefix sum of [5,10,15,20] are themselves divisible by 5, while also forming sub-array sums divisible by 5
61+
// with 10 [5,5] - 5 [5] == 5, 15 [5,5,5] - 5 [5] == 10, etc.
62+
int result = (map[0] ?? 0);
63+
// The prefix sums with the same remainder can form sub-array sums that is divisible by 'k' with each other.
64+
// For each remainder, the number of sub-array that is divisible by 'k' is the number of combinations from the frequency.
65+
// Equation for the number of combinations of n items is n * "(n - 1) / 2".
66+
for (int frequency in map.values)
67+
result += frequency * (frequency - 1) ~/ 2;
68+
return result;
69+
}
70+
}
71+
```
72+
73+
## Prefix Sum & Counting
74+
75+
## Complexity
76+
77+
### Time Complexity: O(n + k)
78+
79+
where 'n' is the length of 'nums'.
80+
We traverse 'nums' once and the counting array of size 'k' once.
81+
82+
### Space Complexity: O(k)
83+
84+
as we create a counting array of size 'k'.
85+
86+
## Code
87+
88+
```dart
89+
class Solution {
90+
int subarraysDivByK(List<int> nums, int k) {
91+
// Use counting array to record the frequency of all the prefix sum remainders.
92+
List<int> counting = List.filled(k, 0);
93+
for (int i = 0; i < nums.length; i++) {
94+
if (i > 0) nums[i] += nums[i - 1];
95+
// Note that the integer in 'nums' can be negative.
96+
// Thus, we need to adjust the negative remainder to positive remainder.
97+
// Below accounts for both negative and positive remainders.
98+
// We can also check if the remainder is negative, then add a 'k' to make the remainder positive.
99+
// For Example, nums = [-2,3,2], k = 5,
100+
// remainder for the prefix sum of [-2,1,3] are -2, 1 and 3 respectively.
101+
// We know that [3,2] sum to 5, which is divisible by 5.
102+
// After converting -2 to 3, by adding 5, it has the same remainder with prefix sum 3.
103+
counting[(nums[i] % k + k) % k]++;
104+
}
105+
106+
// The result contains all the prefix sum with remainder 0,
107+
// as all the prefix sum with remainder of 0 is itself divisible by 'k'.
108+
// However, do note that the prefix sum with remainder 0 also able to form sub-array sums that is divisible by 'k'
109+
// with one another, which will be calculated next.
110+
// For Example: nums = [5,5,5,5], k = 5,
111+
// The prefix sum of [5,10,15,20] are themselves divisible by 5, while also forming sub-array sums divisible by 5
112+
// with 10 [5,5] - 5 [5] == 5, 15 [5,5,5] - 5 [5] == 10, etc.
113+
int result = counting[0];
114+
115+
// The prefix sums with the same remainder can form sub-array sums that is divisible by 'k' with each other.
116+
// For each remainder, the number of sub-array that is divisible by 'k' is the number of combinations from the frequency.
117+
// Equation for the number of combinations of n items is n * "(n - 1) / 2".
118+
for (int frequency in counting) result += frequency * (frequency - 1) ~/ 2;
119+
120+
return result;
121+
}
122+
}
123+
```
124+
125+
## Code
126+
127+
```dart
128+
class Solution {
129+
int subarraysDivByK(List<int> nums, int k) {
130+
int sum = 0;
131+
int cnt = 0;
132+
HashMap<int, int> hm = HashMap();
133+
hm[0] = 1;
134+
for (int i = 0; i < nums.length; i++) {
135+
sum += nums[i];
136+
137+
int diff = sum % k;
138+
139+
if (diff < 0) {
140+
diff += k;
141+
}
142+
143+
if (hm.containsKey(diff)) {
144+
cnt += hm[diff]!;
145+
}
146+
hm[diff] = (hm[diff] ?? 0) + 1;
147+
}
148+
return cnt;
149+
}
150+
}
151+
```

0 commit comments

Comments
 (0)