leetcode
leetcode 1751 ~ 1800
分割数组的最多方案数

分割数组的最多方案数

难度:

标签:

题目描述

代码结果

运行时间: 718 ms, 内存: 42.4 MB


/*
 * 思路:
 * 1. 计算数组的总和totalSum。
 * 2. 使用Java Stream遍历数组,计算每个可能的pivot左侧和右侧的和。
 * 3. 如果找到符合条件的pivot,增加计数。
 * 4. 尝试将数组中的每个元素修改为k,再次检查是否符合条件。
 */
import java.util.stream.IntStream;

public class Solution {
    public int waysToPartition(int[] nums, int k) {
        int n = nums.length;
        long totalSum = IntStream.of(nums).asLongStream().sum();
        long[] leftSums = new long[n];
        long[] rightSums = new long[n];

        leftSums[0] = nums[0];
        for (int i = 1; i < n; i++) {
            leftSums[i] = leftSums[i - 1] + nums[i];
        }

        rightSums[n - 1] = nums[n - 1];
        for (int i = n - 2; i >= 0; i--) {
            rightSums[i] = rightSums[i + 1] + nums[i];
        }

        long ways = IntStream.range(1, n)
            .filter(pivot -> leftSums[pivot - 1] == rightSums[pivot])
            .count();

        for (int i = 0; i < n; i++) {
            long newTotalSum = totalSum - nums[i] + k;

            ways += IntStream.range(1, n)
                .filter(pivot -> (pivot - 1 == i ? k : leftSums[pivot - 1]) == (pivot == i ? k : rightSums[pivot]))
                .count();
        }

        return (int) ways;
    }
}

解释

方法:

本题解的思路基于前缀和的概念。首先,计算数组nums的前缀和数组s。接着,使用两个哈希表left和right来记录在当前位置左侧和右侧各个前缀和出现的次数。对于数组中的每个位置,检查通过替换当前位置的元素为k后,是否存在一种分割方式,使得左右两部分的和相等。如果存在,则更新最大分割方案数。最后,返回最大的分割方案数。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在题解中提到使用两个哈希表来记录前缀和的出现次数,这种方法是否考虑了数组中存在负数或零的情况,这会对计算结果有什么影响?
使用哈希表记录前缀和的出现次数的方法完全可以处理数组中存在负数或零的情况。前缀和是指从数组的第一个元素开始到当前元素的所有元素的累加和,因此无论元素值是正数、负数还是零,前缀和都能正确计算并记录。每个前缀和作为哈希表的键,不影响其计数功能。总体来说,数组中元素的具体值(正数、负数、零)不会影响前缀和的计算逻辑,只会影响最终的前缀和值,而哈希表正是用来根据这些值进行计数的,因此这种方法是有效的。
🦆
题解中提到如果s[-1] % 2 == 0,则检查初始分割方案数。为什么只有当数组总和是偶数时,我们才考虑初始分割方案数?
如果数组的总和(即s[-1])是偶数,那么存在一种可能将数组分割成两个和相等的部分,因为只有当总和是偶数时,总和的一半(s[-1] / 2)也是一个整数,这是将总和平均分配到两个部分的前提。如果总和是奇数,则不可能将其平均分成两个相等的整数部分,因此在总和为奇数的情况下,无需检查初始分割方案数。这是因为不存在一个有效的分割点使得两部分的和相等。
🦆
为何在遍历数组时,需要同时更新左侧和右侧的哈希表?这样做的具体目的是什么?
在遍历数组时,同时更新左侧和右侧的哈希表是为了保持对各部分前缀和出现次数的准确记录。左侧哈希表记录从数组开始到当前元素的前缀和的出现次数,而右侧哈希表记录当前元素之后的前缀和的出现次数。这样做的目的是为了在考虑每个可能的分割点时,能够快速查询任何给定的前缀和在左侧和右侧出现的次数。当考虑替换任一元素后,这种动态更新策略允许我们有效地重新计算可能的分割方案数,而无需重新遍历整个数组。这对于保持算法效率至关重要。

相关问题