LeetCode 3010: Divide an Array Into Subarrays With Minimum Cost I (Pick Two Minimum in Suffix)
LeetCode 3010ArrayGreedyToday we solve LeetCode 3010 - Divide an Array Into Subarrays With Minimum Cost I.
Source: https://leetcode.com/problems/divide-an-array-into-subarrays-with-minimum-cost-i/
English
Problem Summary
Split the array into exactly three contiguous subarrays. The cost is the sum of the first element of each subarray. Return the minimum possible total cost.
Key Insight
The first subarray must start at index 0, so nums[0] is always included. For the other two subarrays, we only need two cut starts from suffix nums[1..], so we should pick the two smallest values there.
Algorithm
Scan nums[1..n-1] once and maintain smallest and second smallest values. Answer is nums[0] + min1 + min2.
Complexity
Time O(n), space O(1).
Reference Implementations (Java / Go / C++ / Python / JavaScript)
class Solution {
public int minimumCost(int[] nums) {
int a = Integer.MAX_VALUE, b = Integer.MAX_VALUE;
for (int i = 1; i < nums.length; i++) {
int x = nums[i];
if (x < a) { b = a; a = x; }
else if (x < b) { b = x; }
}
return nums[0] + a + b;
}
}func minimumCost(nums []int) int {
const inf = int(1e9)
a, b := inf, inf
for i := 1; i < len(nums); i++ {
x := nums[i]
if x < a { b, a = a, x } else if x < b { b = x }
}
return nums[0] + a + b
}class Solution {
public:
int minimumCost(vector<int>& nums) {
int a = INT_MAX, b = INT_MAX;
for (int i = 1; i < (int)nums.size(); ++i) {
int x = nums[i];
if (x < a) { b = a; a = x; }
else if (x < b) b = x;
}
return nums[0] + a + b;
}
};class Solution:
def minimumCost(self, nums: List[int]) -> int:
a = b = 10**18
for x in nums[1:]:
if x < a:
a, b = x, a
elif x < b:
b = x
return nums[0] + a + bvar minimumCost = function(nums) {
let a = Number.MAX_SAFE_INTEGER, b = Number.MAX_SAFE_INTEGER;
for (let i = 1; i < nums.length; i++) {
const x = nums[i];
if (x < a) { b = a; a = x; }
else if (x < b) { b = x; }
}
return nums[0] + a + b;
};中文
题目概述
把数组分成恰好 3 个连续子数组,总代价是每个子数组首元素之和,求最小总代价。
核心思路
第一个子数组一定从下标 0 开始,所以 nums[0] 固定计入。后两个子数组的起点都来自后缀 nums[1..],因此只需在后缀中选出两个最小值。
算法步骤
线性扫描 nums[1..],维护最小值与次小值,答案即 nums[0] + min1 + min2。
复杂度分析
时间复杂度 O(n),额外空间复杂度 O(1)。
多语言参考实现(Java / Go / C++ / Python / JavaScript)
class Solution {
public int minimumCost(int[] nums) {
int a = Integer.MAX_VALUE, b = Integer.MAX_VALUE;
for (int i = 1; i < nums.length; i++) {
int x = nums[i];
if (x < a) { b = a; a = x; }
else if (x < b) { b = x; }
}
return nums[0] + a + b;
}
}func minimumCost(nums []int) int {
const inf = int(1e9)
a, b := inf, inf
for i := 1; i < len(nums); i++ {
x := nums[i]
if x < a { b, a = a, x } else if x < b { b = x }
}
return nums[0] + a + b
}class Solution {
public:
int minimumCost(vector<int>& nums) {
int a = INT_MAX, b = INT_MAX;
for (int i = 1; i < (int)nums.size(); ++i) {
int x = nums[i];
if (x < a) { b = a; a = x; }
else if (x < b) b = x;
}
return nums[0] + a + b;
}
};class Solution:
def minimumCost(self, nums: List[int]) -> int:
a = b = 10**18
for x in nums[1:]:
if x < a:
a, b = x, a
elif x < b:
b = x
return nums[0] + a + bvar minimumCost = function(nums) {
let a = Number.MAX_SAFE_INTEGER, b = Number.MAX_SAFE_INTEGER;
for (let i = 1; i < nums.length; i++) {
const x = nums[i];
if (x < a) { b = a; a = x; }
else if (x < b) { b = x; }
}
return nums[0] + a + b;
};
Comments