You are given a non-negative integer array nums
. In one operation, you must:
x
such that x
is less than or equal to the smallest non-zero element in nums
.x
from every positive element in nums
.Return the minimum number of operations to make every element in nums
equal to 0
.
For example, given nums = [1, 5, 0, 3, 5]
, the output should be 3
. Here's why:
x = 1
. Now, nums = [0, 4, 0, 2, 4]
. The smallest non-zero element was 1
and we subtracted it from every positive element.x = 2
. Now, nums = [0, 2, 0, 0, 2]
. The smallest non-zero element was 2
and we subtracted it from every positive element.x = 2
. Now, nums = [0, 0, 0, 0, 0]
. The smallest non-zero element was 2
and we subtracted it from every positive element.As another example, if nums = [0]
, the output should be 0
because each element in nums
is already 0
so no operations are needed. Write an algorithm to efficiently calculate the minimum number of operations needed to make every element in nums
equal to 0
.
You are given a non-negative integer array nums
. In one operation, you must:
x
such that x
is less than or equal to the smallest non-zero element in nums
.x
from every positive element in nums
.Return the minimum number of operations to make every element in nums
equal to 0
.
Input: nums = [1,5,0,3,5]
Output: 3
Explanation:
In the first operation, choose x = 1. Now, nums = [0,4,0,2,4].
In the second operation, choose x = 2. Now, nums = [0,2,0,0,2].
In the third operation, choose x = 2. Now, nums = [0,0,0,0,0].
The naive approach would be to simulate the operations as described in the problem statement. We repeatedly find the smallest non-zero element in the array, and then subtract that value from all positive elements. We continue this process until all elements are zero. This will definitely give us the correct answer, but it will be slow if the array contains large numbers and small differences between the elements.
def min_operations_naive(nums):
operations = 0
while any(nums):
smallest_positive = float('inf')
for num in nums:
if num > 0 and num < smallest_positive:
smallest_positive = num
if smallest_positive == float('inf'): # no positive number
break
for i in range(len(nums)):
if nums[i] > 0:
nums[i] -= smallest_positive
operations += 1
return operations
The key observation is that the number of operations is equal to the number of distinct positive numbers in the array. We can prove this by induction. The base case is trivial. Assume the statement is true for an array with k distinct positive numbers. If we have k+1 distinct positive numbers, let x be the smallest of those numbers. After subtracting x from all positive numbers, the number x becomes zero, and all other positive numbers are reduced by x. Now we only have k distinct positive numbers to remove. Thus, by induction, we only need k + 1 steps.
def min_operations_optimal(nums):
return len(set(num for num in nums if num > 0))
The optimal solution uses a set
to keep track of distinct values. Iterating through the array takes O(n) time. Creating the set also takes O(n) time in the worst case, where n is the length of the input array nums
. Therefore, the overall time complexity is O(n).
The naive solution, in the worst case, can have a runtime of O(m*n), where n is the length of the array and m is the value of the largest number in the array. This is because it would loop through the entire array m times.
The optimal solution uses a set
to store the distinct positive numbers. In the worst case, all numbers are distinct and positive, so the set will store n
numbers, where n
is the length of nums
. Therefore, the space complexity is O(n).
The naive solution has a space complexity of O(1) because it modifies the input array in-place.
1 <= nums.length <= 100
, so we don't need to handle an empty array.len(set()) == 0
.