I am trying to solve this question and my implementation of binary search exceeds time limit. When I use bisect_left it runs faster and is accepted. Below is my approach.
def bs(self,new,k,n):
st=0
end=n
while st<end:
mid=(st+end)//2
if new[mid]<k:
st=mid+1
else:
end=mid
return st
def smallerSum(self, n : int, arr : List[int],val) -> List[int]:
new = sorted(arr)
cum=[0 for _ in range(n+1)]
for i in range(0,n):
cum[i+1]=cum[i]+new[i]
ans=[0 for _ in range(n)]
for i in range(n):
if val==0:
ans[i] = cum[bisect_left(new,arr[i])]
else:
ans[i]= cum[self.bs(new,arr[i],n)]
return ans
I tried to measure time for 10^5 random integers time taken by my implementation is around .33 seconds while bisect_left takes only 0.13 seconds. Complete code I used to measure time
from typing import List
from bisect import bisect_left,bisect_right
import random
import time
class Solution:
def bs(self,new,k,n):
st=0
end=n
while st<end:
mid=(st+end)//2
if new[mid]<k:
st=mid+1
else:
end=mid
return st
def smallerSum(self, n : int, arr : List[int],val) -> List[int]:
new = sorted(arr)
cum=[0 for _ in range(n+1)]
for i in range(0,n):
cum[i+1]=cum[i]+new[i]
ans=[0 for _ in range(n)]
for i in range(n):
if val==0:
ans[i] = cum[bisect_left(new,arr[i])]
else:
ans[i]= cum[self.bs(new,arr[i],n)]
return ans
if __name__=="__main__":
n = 10**5
arr=[]
for i in range(n):
arr.append(random.randint(0,10**9))
obj = Solution()
st=time.time()
res = obj.smallerSum(n,arr,0)
end=time.time()
print(end-st)
st=time.time()
res = obj.smallerSum(n,arr,1)
end=time.time()
print(end-st)
Why there is such time difference and why bisect_left is faster?
As mentioned by @SuperStormer https://github.com/python/cpython/blob/7cb3a4474731f52c74b19dd3c99ca06e227dae3b/Lib/bisect.py#L72 python3 uses a faster C implementation which is why bisect_left takes lesser time.