[LeetCode] 3356. Zero Array Transformation II
Problem
https://leetcode.com/problems/zero-array-transformation-ii/description
Leetcode - Zero Array Transformation
Type - Binary Search, Parametric Search, Line Sweeping
Difficulty - Medium
Approach & Solution
We can solve it with binary search and line sweeping. In common, two approach uses diff array to accumulate changes. If diff[i] = 3, actual data for num[i] is num[i] - 3. Given l, r, val in queries, update diff like:
diff[l] += valdiff[r+1] += val
Binary Search: starting from lo = 0, hi = k. If k(mid) is available to set 0-array, reduce right side and try the number with less than k to minimize the answer, otherwise, reduce left side and try to larger k.
Line Sweeping: set pointer k to track the amount of used queries. slide k to right while current nums[i] is positive.
** data structure and variables**:
diff: diff[i] stores how much subtracted from nums[i].
Binary Search:
set
l := 0,r := queries.length.follow these steps while
l <= r:set
mid := (l+r)/2if setting with first
kqueries is able,- set
ans = kandr = mid-1to try less thank.
- set
otherwise,
- set
l = mid+1to try greater thank
- set
Line Sweeping:
set
k = 0, sum = 0follow these steps while
i = {0 .. n}:follow these steps while
sum + diff[i] < nums[i]:increment
kby 1. return-1ifkis greater thanqueries.length.update
diff[i]fromqueries[k].
accumulate
diff[i]to sum.
It it valid. so return
k.
Complexity
Time Complexity:
Binary Search:
O((n+q) * log(q))- Validation takesn+qwith validatinglog(q)times.Line Sweeping:
O(n + q)- we iterate nums and queries once.
Space Complexity: O(n) - diff array stores n+1 cells.
Code (C++ | Go)
C++ code is Binary Search code, while golang code uses line sweeping.
#pragma GCC optimize("O3", "unroll-loops");
static const int __ = [](){
ios_base::sync_with_stdio(0);
cin.tie(0);
return 0;
}();
class Solution {
public:
bool check(int k, vector<int>& nums, vector<vector<int>>& queries) {
int n = nums.size();
vector<int> diff(n+1);
for(int i = 0; i < k; i++) {
diff[queries[i][0]] -= queries[i][2];
diff[queries[i][1]+1] += queries[i][2];
}
int d = 0;
for(int i = 0; i < n; i++) {
d += diff[i];
int x = nums[i] + d;
if(x > 0) return false;
}
return true;
}
int minZeroArray(vector<int>& nums, vector<vector<int>>& queries) {
int l = 0;
int r = queries.size();
int ans = -1;
while(l <= r) {
int mid = (l+r)/2;
if(check(mid, nums, queries)) {
ans = mid;
r = mid-1;
} else {
l = mid+1;
}
}
return ans;
}
};
func minZeroArray(nums []int, queries [][]int) int {
diff := make([]int, len(nums)+1)
k := 0
sum := 0
for i := 0; i < len(nums); i++ {
for sum + diff[i] < nums[i] {
k++
if k > len(queries) {
return -1
}
l, r, v := queries[k-1][0], queries[k-1][1], queries[k-1][2]
if r >= i {
diff[max(l, i)] += v
diff[r+1] -= v
}
}
sum += diff[i]
}
return k
}