分割数组

博客围绕数组划分问题展开,给定数组 A ,需将其划分为不相交的连续子数组 left 和 right ,满足 left 元素小于等于 right 元素,left 非空且尽可能小。给出示例并提示数组长度和元素范围,还介绍了一种时间复杂度 O(n)、空间复杂度 O(n) 的解法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

给定一个数组 A ,将其划分为两个不相交(没有公共元素)的连续子数组 left 和 right , 使得:

left 中的每个元素都小于或等于 right 中的每个元素。
left 和 right 都是非空的。
left 要尽可能小。
在完成这样的分组后返回 left 的 长度 。可以保证存在这样的划分方法。

示例 1:

输入:[5,0,3,8,6]
输出:3
解释:left = [5,0,3],right = [8,6]

示例 2:

输入:[1,1,1,0,6,12]
输出:4
解释:left = [1,1,1,0],right = [6,12]

提示:

2 <= A.length <= 30000
0 <= A[i] <= 10^6
可以保证至少有一种方法能够按题目所描述的那样对 A 进行划分。

 

解法一:

先正向扫描一遍数组,找到左区间的最小值,然后在从后向前扫描数组,找到右区间的最小值,最后综合得到的左区间的最大右区间的最小得出答案。时间复杂度O(n),空间复杂度O(n)

public static List<List<Integer>> smallestRangeI1I(int[] A) {
        if (null == A || A.length == 0) {
            return Collections.emptyList();
        }

        int[][] tmp = new int[2][A.length];
        for (int i = 0; i < A.length; i++) {
            tmp[0][i] = i == 0 || A[i] > tmp[0][i - 1] ? A[i] : tmp[0][i - 1];
            tmp[1][A.length - 1 - i] = i == 0 || A[A.length - 1 - i] < tmp[1][A.length - i] ? A[A.length - 1 - i] : tmp[1][A.length - i];
        }

        List<Integer> left = new ArrayList<Integer>();
        List<Integer> right = new ArrayList<Integer>();
        int index = 0;
        while (index < A.length - 1) {
            left.add(A[index]);
            if (tmp[0][index] < tmp[1][index + 1]) {
                break;
            }
            index++;
        }

        index++;
        while (index < A.length) {
            right.add(A[index]);
            index++;
        }

        List<List<Integer>> result = new ArrayList<List<Integer>>();
        result.add(left);
        result.add(right);
        return result;
    }

 

解法二

public static List<List<Integer>> partitionDisjoint1(int[] A) {
        int rightMax = A[0];
        int leftMax = A[0];
        int index = 0;
        for (int i = 0; i < A.length; i++) {
            rightMax = Math.max(rightMax, A[i]);
            if (A[i] < leftMax) {
                leftMax = rightMax;
                index = i;
            }
        }

        List<Integer> left = new ArrayList<Integer>();
        for(int i = 0; i<=index; i++){
            left.add(A[i]);
        }

        List<Integer> right = new ArrayList<Integer>();
        for(int i = index + 1; i < A.length; i ++){
            right.add(A[i]);
        }

        List<List<Integer>> result = new ArrayList<List<Integer>>();
        result.add(left);
        result.add(right);
        return result;
    }

 

### Java 中分割数组的方法或实现方式 在 Java 中,`String.split()` 方法主要用于字符串的拆分操作。然而,在处理数组时,通常会涉及将一个字符串按照特定规则转换为数组或者对现有数组进行重新划分。以下是几种常见的方法来实现数组分割。 #### 使用 `String.split()` 将字符串转化为数组 如果目标是从字符串创建数组,则可以利用 `String.split(regex)` 方法。此方法接受一个正则表达式作为参数,并返回由该正则表达式匹配项分隔的结果字符串数组[^1]。 ```java // 示例:通过英文句号分割字符串并形成数组 public class Main { public static void main(String[] args) { String input = "aa.bb.cc"; String delimiter = "\\."; // 转义后的英文句号 String[] resultArray = input.split(delimiter); for (int i = 0; i < resultArray.length; i++) { System.out.println(resultArray[i]); } } } ``` 以上代码展示了如何使用转义符 `\.` 来正确识别英文句号作为分隔符。 #### 利用自定义逻辑分割数组 对于更复杂的场景,比如需要依据某些条件动态调整数组内容的情况,可能无法单纯依赖内置函数完成任务。此时可以通过编写循环结构配合条件判断语句来自行构建新的子数组集合[^2]。 下面是一个例子,展示如何手动实现类似于题目描述中的功能——即把整数列表划分为若干个连续递增序列: ```java import java.util.*; class Solution { public boolean isPossible(int[] nums) { Map<Integer, Integer> freqMap = new HashMap<>(); Map<Integer, Integer> appendFreq = new HashMap<>(); for (int num : nums){ freqMap.put(num,freqMap.getOrDefault(num,0)+1); } for (int num : nums){ if(freqMap.get(num)==0){continue;} if(appendFreq.containsKey(num)&&appendFreq.get(num)>0){ appendFreq.put(num , appendFreq.get(num)-1 ); appendFreq.put(num+1 , appendFreq.getOrDefault(num+1,0)+1 ); }else{ if(!freqMap.containsKey(num+1)||!freqMap.containsKey(num+2)){ return false; } freqMap.put(num+1,freqMap.get(num+1)-1); freqMap.put(num+2,freqMap.get(num+2)-1); appendFreq.put(num+3,appendFreq.getOrDefault(num+3,0)+1); } freqMap.put(num,freqMap.get(num)-1); } return true; } } public class TestSplitSubsequence { public static void main(String[] args) { int [] testInput={1,2,3,3,4,5}; Solution sol=new Solution(); System.out.print(sol.isPossible(testInput)); } } ``` 上述程序实现了验证输入数组能否被分解成至少三个长度大于等于三的不同连续子串的功能[^2]。 #### 总结 无论是简单的基于固定模式切割还是复杂条件下重组数据集的操作都可以借助于不同的技术手段达成目的。前者适合标准化程度较高的场合;后者适用于灵活性需求较大的环境之中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值