Reputation: 2759
find longest subarray whose sum divisible by K. It is possible in O(n)? If not can it be done in better then n^2 ?
Upvotes: 1
Views: 4679
Reputation: 618
as rightly pointed out by @IVIad you have to keep a track of the current
sum modulo k.
you can write it as s=0
s=(s+arr1[i])%k
after that in a for loop you can use a dictionary and see if the
s is present in dictionary ;
if yes then update the length else update the dictionary .
below is the code.
def longestsubsarraywithsumdivisiblebyk(arr1,k):
h={}
h[0]=-1
maxlen=0
s=0
for i in range(len(arr1)):
s=(s+arr1[i])%k
if s in h:
maxlen=max(maxlen,i-h[s])
else:
h[s]=i
return maxlen
Upvotes: 0
Reputation: 8701
As suggested in previous answers, this can be done in O(N) time and space. Those other answers mention hashing and sorting. However, neither is needed for this problem. In following python program that illustrates a one-pass O(N) method, rr
is the input array, vb[x]
is the index of the first subsum with modular value x
, and ve[x]
is the index of the last subsum with modular value x
. Typical output is shown after the program.
import random
K, N, vmax = 10, 25, 99
rr = [random.randrange(vmax) for x in range(N)]
print 'rr', rr
vb, ve = [-1 for x in range(K)], [-1 for x in range(K)]
vb[0] = ve[0] = mb = me = ms = s = 0
for i in range(N):
s = (s + rr[i]) % K
ve[s] = i+1
if vb[s] < 0:
vb[s] = i+1
if ve[s] - vb[s] > me - mb:
mb, me, ms = vb[s], ve[s], s
print "Max len is", me-mb, "for rem", ms, "at [", mb,":",me, "], total=", sum(rr[mb:me])
Typical output, for K=10 and N=25:
rr [26, 57, 0, 70, 33, 94, 23, 60, 62, 3, 28, 14, 12, 72, 6, 86, 29, 10, 60, 50, 21, 37, 40, 96, 73]
Max len is 21 for rem 3 at [ 2 : 23 ], total= 810
Upvotes: 0
Reputation: 43477
Let s[i] = sum of first i elements modulo K
.
We have:
s[i] = (s[i - 1] + a[i]) % K
We have to find, for each i
, the smallest j
such that s[i] == s[j]
. You can find this by hashing the s[i]
values. If K
is small, you can just keep an array p[i] = first position for which s[k] == i
.
The complexity is O(n)
.
Upvotes: 8
Reputation: 639
function longestRangeDividableBy(k) {
arrayOfRanges
sum =0
startIndex = 0
endIndex = 0
for ( i=0 ; i < array.size; i++) {
sum += array[i]
if (sum % k != 0) {
endindex = i
} else {
arrayOfRanges.add(new Range(startIndex, endIndex);
startIndex = i+1
sum = 0
}
}
arrayOfRanges.sortDescending();
return arrayOfRanges.get(0).lengthOfRange()
}
Here I say the search of the ranges is linear. Thus it depends on the sort wether the algorithm is O(n) or n^2. Correct me if I'm wrong, please.
Upvotes: 0