• LeetCode每日一题(689. Maximum Sum of 3 Non-Overlapping Subarrays)


    Given an integer array nums and an integer k, find three non-overlapping subarrays of length k with maximum sum and return them.

    Return the result as a list of indices representing the starting position of each interval (0-indexed). If there are multiple answers, return the lexicographically smallest one.

    Example 1:

    Input: nums = [1,2,1,2,6,7,5,1], k = 2
    Output: [0,3,5]

    Explanation: Subarrays [1, 2], [2, 6], [7, 5] correspond to the starting indices [0, 3, 5].
    We could have also taken [2, 1], but an answer of [1, 3, 5] would be lexicographically larger.

    Example 2:

    Input: nums = [1,2,1,2,1,2,1,2,1], k = 2
    Output: [0,2,4]

    Constraints:

    • 1 <= nums.length <= 2 * 104
    • 1 <= nums[i] < 216
    • 1 <= k <= floor(nums.length / 3)

    直接用 dp 来解会超时, 想了半天也没想到优化的办法。开始看答案。答案不难理解, 但是如果没有提示, 恐怕自己很难会往这个方向去想。

    首先我们定义一个数组 w, w[i]代表从 nums[i]到 nums[i+k-1]的加和, 然后我们再对 w 做 prefix sum 和 suffix sum, 分别是 left 和 right, 这时要注意, 这两个 sum 中都是保存的最大值的 index, 也就是说 left[i]代表的是从 w[0]到 w[i]中最大值的 index, right[i]代表的是从 w[i]到 w[last]的最大值的 index, 无论是 left 还是 right, 相同的 w[i]值取相对小的 index。然后假设我们通过三个值,i, j, l, 将 w 分成三份, 那中间的 j 的取值范围就是 k < j < w.len() - k, 这时左边那部分的最大值就是 w[left[j-k]], 也就是从 w[0]到 w[j-k]中的最大值, 右边那部分的最大值是 w[right[j+k]], 也就是从 w[j+k]到 w[last]中的最大值, 中间部分的值是 w[j], 遍历 j, 每次将这三部分相加,取最大值即可


    
    impl Solution {
        pub fn max_sum_of_three_subarrays(nums: Vec<i32>, k: i32) -> Vec<i32> {
            let mut w = vec![0; nums.len() - k as usize + 1];
            let mut queue: Vec<i32> = Vec::new();
            let mut sum = 0;
            for i in 0..nums.len() {
                queue.push(nums[i]);
                sum += nums[i];
                if queue.len() > k as usize {
                    sum -= queue.remove(0);
                }
                if queue.len() == k as usize {
                    w[i + 1 - k as usize] = sum;
                }
            }
            let mut max = 0;
            let mut left = vec![0; w.len()];
            for i in 0..w.len() {
                if w[i] > w[max] {
                    max = i;
                }
                left[i] = max;
            }
            max = w.len() - 1;
            let mut right = vec![0; w.len()];
            for i in (0..w.len()).rev() {
                if w[i] >= w[max] {
                    max = i;
                }
                right[i] = max;
            }
            let mut ans = Vec::new();
            let mut max = 0;
            for j in k as usize..w.len() - k as usize {
                if w[left[j - k as usize]] + w[j] + w[right[j + k as usize]] > max {
                    max = w[left[j - k as usize]] + w[j] + w[right[j + k as usize]];
                    ans = vec![left[j - k as usize] as i32, j as i32, right[j + k as usize] as i32];
                }
            }
            ans
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
  • 相关阅读:
    【工具免费】喜马拉雅 x2m转m4a,xm转mp3的简单方法!
    JVM中的-Xms -Xmx -XXnewSize -XXMaxnewSize -Xmn -XXPermSize -XXMaxPermSize区别介绍
    Promise.all如果其中之一失败,怎么能够拿到其他成功的结果
    CentOS7源码安装 lldpd 并附查询脚本
    历时一年 Apache Spark 3.3.0 正式发布,新特性详解
    Python中最快的循环方式
    流程控制.
    php Unicode编码格式案例
    【数组】逐步求和得到正数的最小值
    【C语言】宏定义
  • 原文地址:https://blog.csdn.net/wangjun861205/article/details/128124559