[LeetCode] 1526. Minimum Number of Increments on Subarrays to Form a Target Array
Given an array of positive integers target
and an array initial
of same size with all zeros.
Return the minimum number of operations to form a target
array from initial
if you are allowed to do the following operation:
- Choose any subarray from
initial
and increment each value by one.
The answer is guaranteed to fit within the range of a 32-bit signed integer.
Example 1:
Input: target = [1,2,3,2,1] Output: 3 Explanation: We need at least 3 operations to form the target array from the initial array. [0,0,0,0,0] increment 1 from index 0 to 4 (inclusive). [1,1,1,1,1] increment 1 from index 1 to 3 (inclusive). [1,2,2,2,1] increment 1 at index 2. [1,2,3,2,1] target array is formed.
Example 2:
Input: target = [3,1,1,2] Output: 4 Explanation: (initial)[0,0,0,0] -> [1,1,1,1] -> [1,1,1,2] -> [2,1,1,2] -> [3,1,1,2] (target).
Example 3:
Input: target = [3,1,5,4,2] Output: 7 Explanation: (initial)[0,0,0,0,0] -> [1,1,1,1,1] -> [2,1,1,1,1] -> [3,1,1,1,1] -> [3,1,2,2,2] -> [3,1,3,3,2] -> [3,1,4,4,2] -> [3,1,5,4,2] (target).
Example 4:
Input: target = [1,1,1,1] Output: 1
Constraints:
1 <= target.length <= 10^5
1 <= target[i] <= 10^5
形成目标数组的子数组最少增加次数。
给你一个整数数组 target 和一个数组 initial ,initial 数组与 target 数组有同样的维度,且一开始全部为 0 。
请你返回从 initial 得到 target 的最少操作次数,每次操作需遵循以下规则:
在 initial 中选择 任意 子数组,并将子数组中每个元素增加 1 。
答案保证在 32 位有符号整数以内。来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-number-of-increments-on-subarrays-to-form-a-target-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
这道题的题意反过来理解就是给一个数组,请问你通过几次操作能把数组的所有元素修改为0。修改的规则是每次只能改一段连续的子数组,并且这一段子数组只能 - 1。
这道题我给出两种做法,其实背后都是同一种思路,类似求前缀和。对于每一个数字 target[i],我们看他与 target[i - 1] 之间的差值,每两个数字之间的差值就是全局需要操作的次数。当这个差值大于0就是操作次数;当这个差值小于0则无需计算,因为我们一开始计算过了最大值和0之间的差值了。
时间O(n)
空间O(n)
Java prefix sum实现
1 class Solution { 2 public int minNumberOperations(int[] target) { 3 int res = 0; 4 int pre = 0; 5 for (int num : target) { 6 res += Math.max(num - pre, 0); 7 pre = num; 8 } 9 return res; 10 } 11 }
Java单调栈实现
1 class Solution { 2 public int minNumberOperations(int[] target) { 3 // corner case 4 if (target.length == 1) { 5 return target[0]; 6 } 7 8 // normal case 9 int res = 0; 10 Stack<Integer> stack = new Stack<>(); 11 stack.push(target[0]); 12 for (int i = 1; i < target.length; i++) { 13 int cur = target[i]; 14 int prev = stack.peek(); 15 if (cur > prev) { 16 stack.push(cur); 17 } else if (cur == prev) { 18 continue; 19 } else { 20 res += stack.pop() - cur; 21 stack.push(cur); 22 } 23 } 24 return res + stack.pop(); 25 } 26 }