Related
I decided to complete some tasks on Leetcode to improve my algorithm skills.
And I ran into a problem with LeetCode's problem 985. Sum of Even Numbers After Queries
Here is the description of that task:
You are given an integer array nums and an array queries where queries[i] = [valᵢ, indexᵢ].
For each query i, first, apply nums[indexᵢ] = nums[indexᵢ] + valᵢ, then print the sum of the even values of nums.
Return an integer array answer where answer[i] is the answer to the ith query.
Some samples of input and output:
# input1: nums = [1,2,3,4], queries = [[1,0],[-3,1],[-4,0],[2,3]]
# output1: [8, 6, 2, 4]
# input2: nums = [1], queries = [[4,0]]
# output2: [0]
So I found the solution, but as it has some huge samples of inputs, I found that my code is not efficient enough.
Here is my code:
class Solution:
def sumEvenAfterQueries(self, nums: list[int], queries: list[list[int]]) -> list[int]:
ans = []
integer_ans = 0
for i in range(len(queries)):
nums[queries[i][1]] = nums[queries[i][1]] + queries[i][0]
for j in nums:
if j % 2 == 0:
integer_ans += j
ans.append(integer_ans)
integer_ans = 0
return ans
So it does not solve problem because of the Time limit exceeded.
How can I improve my code to make it more efficient?
Try this solution. This will initially build up even_nums which are sum of even numbers in list, then incrementally update it with each value in queries.
It's probably not the most efficient, but it works for me. I submit on leetcode just now.
class Solution:
def sumEvenAfterQueries(self, nums: List[int], queries: List[List[int]]) -> List[int]:
even_sum = sum(x for x in nums if not x % 2)
result = []
for (add, i) in queries:
n = nums[i]
if add % 2: # odd
if n % 2: # both odd, result is even
even_sum += n + add
else: # even, add odd, result is odd
even_sum -= n
# odd, add even, result is still odd
# so, both must be even
elif not n % 2: # both even
even_sum += add
# remember updating nums at index #i
# and then adding to ours result
nums[i] = n + add
result.append(even_sum)
return result
Not so optimised solution, but you need to keep update of the sum of even values first and then for every query you run, you need to make the changes for the index of that value and see if sum for that index is calcualed or not. if not then add it to total sum and update the nums and if it is calculate then add the new sum value to it and modify the nums accordingly.
below is a simple way to achive this.
class Solution:
def sumEvenAfterQueries(self, nums: List[int], queries: List[List[int]]) -> List[int]:
dic = {i:v for i, v in enumerate(nums) if v%2==0}
sum_ = sum(dic.values())
res = []
for v, i in queries:
val = nums[i]
new_val = nums[i] + v
if i not in dic:
if new_val%2==0:
dic[i] = new_val
sum_ += new_val
res.append(sum_)
else:
res.append(sum_)
else:
if new_val%2==0:
sum_ -= val
sum_ += new_val
dic[i] = new_val
res.append(sum_)
else:
sum_-= val
del dic[i]
res.append(sum_)
nums[i] = new_val
return res
This is an addition to rv.kvetch answer
Your code is giving TLE because it has the worst case time complexity of O(n2). I hope you know about the it.
Coming to the solution, we can do in in O(n) i.e. linear time.
Algorithm
Initially we will store sum of all even numbers present in nums to all_sum
Adding value to any item of nums list can make nums[index] + value even or odd, we will check these conditions
Based on these conditions checks, we either add (value or nums[index] + value) or subtract nums[index] from all_sum
After all these condition checks we will modify nums[index] to be nums[index] = nums[index] + value and add all_sum to the array that we want to return as answer
Code
def sumEvenAfterQueries(self, nums: List[int], queries: List[List[int]]) -> List[int]:
all_sum = 0
for e in nums:
if e%2 == 0:
all_sum += e
sum_arr = []
for val, index in queries:
if nums[index] % 2 == 0: # nums item is already added to all_sum
if (nums[index] + val) % 2 == 0:
all_sum += val
else:
all_sum -= nums[index]
else: # nums item is odd so it wasn't added to all_sum before
if (nums[index] + val) % 2 == 0:
all_sum += (nums[index] + val)
else:
pass
nums[index] += val
sum_arr.append(all_sum)
return sum_arr
I was going through this closest 3-sum leetcode problem which says:
Given an integer array nums of length n and an integer target, find three integers in nums such that the sum is closest to target.
Return the sum of the three integers.
You may assume that each input would have exactly one solution.
I have created the following solution and this appears correct but it fails with the Time Limit Exceeded error. How could I optimize this code? I have already added one of the optimization I felt but not sure how can I improve this further.
class Solution:
def threeSumClosest(self, nums: List[int], target: int) -> int:
nums.sort()
csum = None
min_diff = float("+inf")
for i in range(0,len(nums)-2):
l = i + 1
r = len(nums)-1
if i > 0 and nums[i] == nums[i-1]:
continue # OPTIMIZATION TO AVOID SAME CALCULATION
while l < r:
sum = nums[i] + nums[l] + nums[r]
diff = abs(target-sum)
if sum == target:
csum = target
min_diff = 0
break
elif sum > target:
r -= 1
else:
l += 1
if min_diff > diff:
min_diff = diff
csum = sum
return nums[0] if csum is None else csum
Maybe this reference approach can help: Try it first and see if you have any question. Note - see this from a recent post, it performs really well - exceeds 90% of submission in Python category.
def threeSumClosest(self, nums: List[int], target: int) -> int:
nums.sort()
return self.kSumClosest(nums, 3, target)
def kSumClosest(self, nums: List[int], k: int, target: int) -> int:
N = len(nums)
if N == k: return sum(nums[:k]) # found it
# too small
tot = sum(nums[:k])
if tot >= target: return tot
# too big
tot = sum(nums[-k:])
if tot <= target: return tot
if k == 1:
return min([(x, abs(target - x)) for x in nums], key = lambda x: x[1])[0]
closest = sum(nums[:k])
for i, x in enumerate(nums[:-k+1]):
if i > 0 and x == nums[i-1]:
continue
current = self.kSumClosest(nums[i+1:], k-1, target - x) + x
if abs(target - current) < abs(target - closest):
if current == target:
return target
else:
closest = current
return closest
I took following codility demo task
Write a function:
def solution(A)
that, given an array A of N integers, returns the smallest positive integer (greater than 0) that does not occur in A.
For example, given A = [1, 3, 6, 4, 1, 2], the function should return 5.
Given A = [1, 2, 3], the function should return 4.
Given A = [−1, −3], the function should return 1.
Write an efficient algorithm for the following assumptions:
N is an integer within the range [1..100,000];
each element of array A is an integer within the range [−1,000,000..1,000,000].
My Solution
def solution(A):
# write your code in Python 3.6
l = len(A)
B = []
result = 0
n = 0
for i in range(l):
if A[i] >=1:
B.append(A[i])
if B ==[]:
return(1)
else:
B.sort()
B = list(dict.fromkeys(B))
n = len(B)
for j in range(n-1):
if B[j+1]>B[j]+1:
result = (B[j]+1)
if result != 0:
return(result)
else:
return(B[n-1]+1)
Although I get correct output for all inputs I tried but my score was just 22%. Could somebody please highlight where I am going wrong.
Python solution with O(N) time complexity and O(N) space complexity:
def solution(A):
arr = [0] * 1000001
for a in A:
if a>0:
arr[a] = 1
for i in range(1, 1000000+1):
if arr[i] == 0:
return i
My main idea was to:
creat a zero-initialized "buckets" for all the positive possibilities.
Iterate over A. Whenever you meet a positive number, mark it's bucket as visited (1).
Iterate over the "buckets" and return the first zero "bucket".
def solution(A):
s = set(A)
for x in range(1,100002):
if x not in s:
return x
pass
And GOT 100%
# you can write to stdout for debugging purposes, e.g.
# print("this is a debug message")
def solution(A):
# write your code in Python 3.6
i = 1;
B = set(A);
while True:
if i not in B:
return i;
i+=1;
My Javascript solution. The solution is to sort the array and compare the adjacent elements of the array. Complexity is O(N)
function solution(A) {
// write your code in JavaScript (Node.js 8.9.4)
A.sort((a, b) => a - b);
if (A[0] > 1 || A[A.length - 1] < 0 || A.length <= 2) return 1;
for (let i = 1; i < A.length - 1; ++i) {
if (A[i] > 0 && (A[i + 1] - A[i]) > 1) {
return A[i] + 1;
}
}
return A[A.length - 1] + 1;
}
in Codility you must predict correctly others inputs, not only the sample ones and also get a nice performance. I've done this way:
from collections import Counter
def maior_menos_zero(A):
if A < 0:
return 1
else:
return 1 if A != 1 else 2
def solution(A):
if len(A) > 1:
copia = set(A.copy())
b = max(A)
c = Counter(A)
if len(c) == 1:
return maior_menos_zero(A[0])
elif 1 not in copia:
return 1
else:
for x in range(1,b+2):
if x not in copia:
return x
else:
return maior_menos_zero(A[0])
Got it 100%. If is an array A of len(A) == 1, function maior_menos_zero will be called. Moreover, if it's an len(A) > 1 but its elements are the same (Counter), then function maior_menos_zero will be called again. Finally, if 1 is not in the array, so 1 is the smallest positive integer in it, otherwise 1 is in it and we shall make a for X in range(1,max(A)+2) and check if its elements are in A, futhermore, to save time, the first ocurrence of X not in A is the smallest positive integer.
My solution (100% acceptance):
def solution(nums):
nums_set = set()
for el in nums:
if el > 0 and el not in nums_set:
nums_set.add(el)
sorted_set = sorted(nums_set)
if len(sorted_set) == 0:
return 1
if sorted_set[0] != 1:
return 1
for i in range(0, len(sorted_set) - 1, 1):
diff = sorted_set[i + 1] - sorted_set[i]
if diff >= 2:
return sorted_set[i] + 1
return sorted_set[-1] + 1
I tried the following, and got 100% score
def solution(A):
A_set = set(A)
for x in range(10**5 + 1, 1):
if x not in A_set:
return x
else:
return 10**5 + 1
This solution is an easy approach!
def solution(A):
... A.sort()
... maxval = A[-1]
... nextmaxval = A[-2]
... if maxval < 0:
... while maxval<= 0:
... maxval += 1
... return maxval
... else:
... if nextmaxval + 1 in A:
... return maxval +1
... else:
... return nextmaxval + 1
This is my solution
def solution(A):
# write your code in Python 3.8.10
new = set(A)
max_ = abs(max(A)) #use the absolute here for negative maximum value
for num in range(1,max_+2):
if num not in new:
return num
Try this, I am assuming the list is not sorted but if it is sorted you can remove the number_list = sorted(number_list) to make it a little bit faster.
def get_smallest_positive_integer(number_list):
if all(number < 0 for number in number_list) or 1 not in number_list:
#checks if numbers in list are all negative integers or if 1 is not in list
return 1
else:
try:
#get the smallest number in missing integers
number_list = sorted(number_list) # remove if list is already sorted by default
return min(x for x in range(number_list[0], number_list[-1] + 1) if x not in number_list and x != 0)
except:
#if there is no missing number in list get largest number + 1
return max(number_list) + 1
print(get_smallest_positive_integer(number_list))
input:
number_list = [1,2,3]
output:
>>4
input:
number_list = [-1,-2,-3]
output:
>>1
input:
number_list = [2]
output:
>>1
input:
number_list = [12,1,23,3,4,5,61,7,8,9,11]
output:
>>2
input:
number_list = [-1,3,2,1]
output:
>>4
I think this should be as easy as starting at 1 and checking which number first fails to appear.
def solution(A):
i = 1
while i in A:
i += 1
return i
You can also consider putting A's elements into a set (for better performance on the search), but I'm not sure that it's worth for this case.
Update:
I've been doing some tests with the numbers OP gave (numbers from negative million to positive million and 100000 elements).
100000 elements:
Linear Search: 0.003s
Set Search: 0.017s
1000000 elements (extra test):
Linear Search: 0.8s
Set Search: 2.58s
I am working on leetcode "762. Prime Number of Set Bits in Binary Representation" and I tested my code works fine on Jupiter Notebook and when I migrate into leetcode it shows null as a ending result. Could someone give me any hint on what the problems are?
class Solution:
def countPrimeSetBits(self, L, R):
"""
:type L: int
:type R: int
:rtype: int
"""
def isPrime(num):
if num == 0:
return False
list1 = list(range(num))
list1.remove(0)
if len(list1) != 0:
list1.remove(num-1)
for i in list1:
if num % (i+1) == 0:
return False
else:
return True
count = 0
for i in range(L, R+1):
newlist = list(bin(i)[2::])
newcount = 0
for j in newlist:
if j == '1':
newcount += 1
if isPrime(newcount) is True:
count += 1
return count
The expect result is 23 for the first test case which is L=842 and R=888
Jupiter Note book gives me back 23 as expected but Leetcode returns null as a result
You have two serious problems. The first is that the code as presented is indented incorrectly, such that the body of code for countPrimeSetBits() is instead part of the internal function isPrime(). The second problem is that, besides being the worst implementation ever, your isPrime() doesn't really work:
>>> isPrime(169)
True
>>> 13 * 13
169
>>>
due to this else clause placing the return at the wrong point in the code:
else:
return True
Below is your patched code which hopefully will work in both environments:
class Solution:
def countPrimeSetBits(self, L, R):
"""
:type L: int
:type R: int
:rtype: int
"""
def isPrime(number):
if number == 0:
return False
divisors = list(range(number))
divisors.remove(0)
if divisors:
divisors.remove(number - 1)
for divisor in divisors:
if number % (divisor + 1) == 0:
return False
return True
count = 0
for i in range(L, R + 1):
newlist = list(bin(i)[2::])
newcount = 0
for j in newlist:
if j == '1':
newcount += 1
if isPrime(newcount):
count += 1
return count
For example:
input: A = [ 6 4 3 -5 0 2 -7 1 ]
output: 5
Since 5 is the smallest positive integer that does not occur in the array.
I have written two solutions to that problem. The first one is good but I don't want to use any external libraries + its O(n)*log(n) complexity. The second solution "In which I need your help to optimize it" gives an error when the input is chaotic sequences length=10005 (with minus).
Solution 1:
from itertools import count, filterfalse
def minpositive(a):
return(next(filterfalse(set(a).__contains__, count(1))))
Solution 2:
def minpositive(a):
count = 0
b = list(set([i for i in a if i>0]))
if min(b, default = 0) > 1 or min(b, default = 0) == 0 :
min_val = 1
else:
min_val = min([b[i-1]+1 for i, x in enumerate(b) if x - b[i - 1] >1], default=b[-1]+1)
return min_val
Note: This was a demo test in codility, solution 1 got 100% and
solution 2 got 77 %.
Error in "solution2" was due to:
Performance tests ->
medium chaotic sequences length=10005 (with minus) got 3 expected
10000
Performance tests -> large chaotic + many -1, 1, 2, 3 (with
minus) got 5 expected 10000
Testing for the presence of a number in a set is fast in Python so you could try something like this:
def minpositive(a):
A = set(a)
ans = 1
while ans in A:
ans += 1
return ans
Fast for large arrays.
def minpositive(arr):
if 1 not in arr: # protection from error if ( max(arr) < 0 )
return 1
else:
maxArr = max(arr) # find max element in 'arr'
c1 = set(range(2, maxArr+2)) # create array from 2 to max
c2 = c1 - set(arr) # find all positive elements outside the array
return min(c2)
I have an easy solution. No need to sort.
def solution(A):
s = set(A)
m = max(A) + 2
for N in range(1, m):
if N not in s:
return N
return 1
Note: It is 100% total score (Correctness & Performance)
def minpositive(A):
"""Given an list A of N integers,
returns the smallest positive integer (greater than 0)
that does not occur in A in O(n) time complexity
Args:
A: list of integers
Returns:
integer: smallest positive integer
e.g:
A = [1,2,3]
smallest_positive_int = 4
"""
len_nrs_list = len(A)
N = set(range(1, len_nrs_list+2))
return min(N-set(A)) #gets the min value using the N integers
This solution passes the performance test with a score of 100%
def solution(A):
n = sorted(i for i in set(A) if i > 0) # Remove duplicates and negative numbers
if not n:
return 1
ln = len(n)
for i in range(1, ln + 1):
if i != n[i - 1]:
return i
return ln + 1
def solution(A):
B = set(sorted(A))
m = 1
for x in B:
if x == m:
m+=1
return m
Continuing on from Niroj Shrestha and najeeb-jebreel, added an initial portion to avoid iteration in case of a complete set. Especially important if the array is very large.
def smallest_positive_int(A):
sorted_A = sorted(A)
last_in_sorted_A = sorted_A[-1]
#check if straight continuous list
if len(sorted_A) == last_in_sorted_A:
return last_in_sorted_A + 1
else:
#incomplete list, iterate to find the smallest missing number
sol=1
for x in sorted_A:
if x == sol:
sol += 1
else:
break
return sol
A = [1,2,7,4,5,6]
print(smallest_positive_int(A))
This question doesn't really need another answer, but there is a solution that has not been proposed yet, that I believe to be faster than what's been presented so far.
As others have pointed out, we know the answer lies in the range [1, len(A)+1], inclusively. We can turn that into a set and take the minimum element in the set difference with A. That's a good O(N) solution since set operations are O(1).
However, we don't need to use a Python set to store [1, len(A)+1], because we're starting with a dense set. We can use an array instead, which will replace set hashing by list indexing and give us another O(N) solution with a lower constant.
def minpositive(a):
# the "set" of possible answer - values_found[i-1] will tell us whether i is in a
values_found = [False] * (len(a)+1)
# note any values in a in the range [1, len(a)+1] as found
for i in a:
if i > 0 and i <= len(a)+1:
values_found[i-1] = True
# extract the smallest value not found
for i, found in enumerate(values_found):
if not found:
return i+1
We know the final for loop always finds a value that was not marked, because it has one more element than a, so at least one of its cells was not set to True.
def check_min(a):
x= max(a)
if x-1 in a:
return x+1
elif x <= 0:
return 1
else:
return x-1
Correct me if i'm wrong but this works for me.
def solution(A):
clone = 1
A.sort()
for itr in range(max(A) + 2):
if itr not in A and itr >= 1:
clone = itr
break
return clone
print(solution([2,1,4,7]))
#returns 3
def solution(A):
n = 1
for i in A:
if n in A:
n = n+1
else:
return n
return n
def not_in_A(a):
a=sorted(a)
if max(a)<1:
return(1)
for i in range(0,len(a)-1):
if a[i+1]-a[i]>1:
out=a[i]+1
if out==0 or out<1:
continue
return(out)
return(max(a)+1)
mark and then find the first one that didn't find
nums = [ 6, 4, 3, -5, 0, 2, -7, 1 ]
def check_min(nums):
marks = [-1] * len(nums)
for idx, num in enumerate(nums):
if num >= 0:
marks[num] = idx
for idx, mark in enumerate(marks):
if mark == -1:
return idx
return idx + 1
I just modified the answer by #najeeb-jebreel and now the function gives an optimal solution.
def solution(A):
sorted_set = set(sorted(A))
sol = 1
for x in sorted_set:
if x == sol:
sol += 1
else:
break
return sol
I reduced the length of set before comparing
a=[1,222,3,4,24,5,6,7,8,9,10,15,2,3,3,11,-1]
#a=[1,2,3,6,3]
def sol(a_array):
a_set=set()
b_set=set()
cnt=1
for i in a_array:
#In order to get the greater performance
#Checking if element is greater than length+1
#then it can't be output( our result in solution)
if i<=len(a) and i >=1:
a_set.add(i) # Adding array element in set
b_set.add(cnt) # Adding iterator in set
cnt=cnt+1
b_set=b_set.difference(a_set)
if((len(b_set)) > 1):
return(min(b_set))
else:
return max(a_set)+1
sol(a)
def solution(A):
nw_A = sorted(set(A))
if all(i < 0 for i in nw_A):
return 1
else:
ans = 1
while ans in nw_A:
ans += 1
if ans not in nw_A:
return ans
For better performance if there is a possibility to import numpy package.
def solution(A):
import numpy as np
nw_A = np.unique(np.array(A))
if np.all((nw_A < 0)):
return 1
else:
ans = 1
while ans in nw_A:
ans += 1
if ans not in nw_A:
return ans
def solution(A):
# write your code in Python 3.6
min_num = float("inf")
set_A = set(A)
# finding the smallest number
for num in set_A:
if num < min_num:
min_num = num
# print(min_num)
#if negative make positive
if min_num < 0 or min_num == 0:
min_num = 1
# print(min_num)
# if in set add 1 until not
while min_num in set_A:
min_num += 1
return min_num
Not sure why this is not 100% in correctness. It is 100% performance
def solution(A):
arr = set(A)
N = set(range(1, 100001))
while N in arr:
N += 1
return min(N - arr)
solution([1, 2, 6, 4])
#returns 3