leetcode
leetcode 2401 ~ 2450
合法分割的最小下标

合法分割的最小下标

难度:

标签:

题目描述

An element x of an integer array arr of length m is dominant if freq(x) * 2 > m, where freq(x) is the number of occurrences of x in arr. Note that this definition implies that arr can have at most one dominant element.

You are given a 0-indexed integer array nums of length n with one dominant element.

You can split nums at an index i into two arrays nums[0, ..., i] and nums[i + 1, ..., n - 1], but the split is only valid if:

  • 0 <= i < n - 1
  • nums[0, ..., i], and nums[i + 1, ..., n - 1] have the same dominant element.

Here, nums[i, ..., j] denotes the subarray of nums starting at index i and ending at index j, both ends being inclusive. Particularly, if j < i then nums[i, ..., j] denotes an empty subarray.

Return the minimum index of a valid split. If no valid split exists, return -1.

 

Example 1:

Input: nums = [1,2,2,2]
Output: 2
Explanation: We can split the array at index 2 to obtain arrays [1,2,2] and [2]. 
In array [1,2,2], element 2 is dominant since it occurs twice in the array and 2 * 2 > 3. 
In array [2], element 2 is dominant since it occurs once in the array and 1 * 2 > 1.
Both [1,2,2] and [2] have the same dominant element as nums, so this is a valid split. 
It can be shown that index 2 is the minimum index of a valid split. 

Example 2:

Input: nums = [2,1,3,1,1,1,7,1,2,1]
Output: 4
Explanation: We can split the array at index 4 to obtain arrays [2,1,3,1,1] and [1,7,1,2,1].
In array [2,1,3,1,1], element 1 is dominant since it occurs thrice in the array and 3 * 2 > 5.
In array [1,7,1,2,1], element 1 is dominant since it occurs thrice in the array and 3 * 2 > 5.
Both [2,1,3,1,1] and [1,7,1,2,1] have the same dominant element as nums, so this is a valid split.
It can be shown that index 4 is the minimum index of a valid split.

Example 3:

Input: nums = [3,3,3,3,7,2,2]
Output: -1
Explanation: It can be shown that there is no valid split.

 

Constraints:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 109
  • nums has exactly one dominant element.

代码结果

运行时间: 83 ms, 内存: 30.7 MB


// Java Stream solution
// 思路:首先找到数组中的支配元素及其出现次数。然后,我们使用Java Stream API来计算左侧和右侧的支配元素的次数,并找到最小的合法分割点。

import java.util.stream.IntStream;
import java.util.stream.Stream;

public class DominantElementSplitStream {
    public int findSplitIndex(int[] nums) {
        int n = nums.length;
        int dominantElement = nums[0];
        int totalCount = (int) Stream.of(nums).filter(x -> x == dominantElement).count();

        for (int i = 1; i < n; i++) {
            if (nums[i] == dominantElement) {
                totalCount++;
            } else if (totalCount == 0) {
                dominantElement = nums[i];
                totalCount = 1;
            } else {
                totalCount--;
            }
        }

        totalCount = (int) IntStream.of(nums).filter(x -> x == dominantElement).count();

        int leftCount = 0;
        for (int i = 0; i < n; i++) {
            if (nums[i] == dominantElement) {
                leftCount++;
            }
            if (leftCount * 2 > i + 1 && (totalCount - leftCount) * 2 > n - i - 1) {
                return i;
            }
        }
        return -1;
    }
}

解释

方法:

本题解使用了贪心加校验的方法。首先,通过统计数组中每个元素的频率,找到支配元素(频率最高且满足支配条件的元素)。接着,从数组的起点开始,逐个元素累加支配元素的出现次数,寻找最小的符合条件的下标i,使得在该下标处分割数组后,左侧子数组的支配元素仍然是整体的支配元素。最后,验证右侧子数组是否满足支配元素的条件。如果都满足,则返回该下标;如果找不到符合条件的下标,则返回-1。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
如何确定数组中只有一个支配元素,且题解中的方法是否确保了这一点?
题解中并没有明确确保数组中只存在一个支配元素,而是通过统计各元素的频率,并选取频率最高的元素作为支配元素。如果存在多个元素具有相同的最高频率,则题解中的方法会选取最后一个满足条件的元素作为支配元素。这并不严格确保只有一个支配元素,只是确保了选取的支配元素在原数组中出现次数最多。
🦆
在统计元素频率时,如何处理多个元素频率相同的情况?题解中似乎只选择了最后一个满足条件的元素作为支配元素。
是的,题解中使用了Python的Counter类来统计频率,并通过遍历Counter的结果来更新找到的频率最高的元素。当多个元素频率相同时,题解中的方法确实只选择了在遍历中最后遇到的满足条件的元素作为支配元素。这可能不是最优的选择,特别是如果考虑支配元素的选取对问题解决的影响。
🦆
题解中的贪心方法是如何确保左侧子数组和右侧子数组的支配元素相同?是否有可能其他元素的频率在右侧子数组中增加使其成为新的支配元素?
题解中的贪心方法主要是通过检查在某个下标处分割后,左侧子数组中的支配元素是否仍然满足支配条件。然而,对于右侧数组,题解仅仅检查了剩余的支配元素频率是否足以让它在右侧仍为支配元素,但没有考虑到其他元素的频率可能在右侧子数组中增加,这可能导致新的支配元素的出现。因此,虽然题解考虑了部分问题,但没有完全确保右侧子数组中不会出现新的支配元素。
🦆
为什么在找到第一个合法分割点后就可以直接结束循环,不再检查之后的分割点是否也可能是合法的?
题解中的方法在找到第一个满足左侧子数组支配元素条件的下标后即结束循环,这是基于贪心策略的决定。贪心策略的目标是尽可能早地找到一个解决方案,并不保证找到的是最优解。此外,一旦找到一个符合条件的分割点,就意味着左侧部分已符合条件,继续寻找其他分割点可能会破坏这一条件,因此在找到第一个符合条件的分割点后停止搜索是合理的。

相关问题