Skip to content

数组元素拆分到多个数组

需求

一个数组中有若干个元素,需要将这若干个元素拆分到 n 个数组中, 每个数组中的元素数量尽量均等。

思路

考虑两种情况:数组元素可以被均等拆分数组元素不能被均等拆分

数组元素可以被均等拆分

第一种情况好办,目标数组元素数量 = 原数组元素数量 / 目标数组个数 count = sourceList / n。假设初始下标 i 为 0,循环 n - 1 次,则有目标数组 targetList[i] 的元素为 sourceList[i * count]sourceList[((i + 1) * count) - 1] 之间的元素。

数组元素不能被均等拆分

这一种情况就有些复杂了,因为拆分到目标数组的元素并不均等,所有会有剩余的元素。假设剩余元素数量为 remainder,偏移量 offset 为 0,则有目标数组 targetList[i] 的元素为 sourceList[i * count + offset]sourceList[((i + 1) * count + (offset + 1)) - 1] 之间的元素。

实现

Java 中的 List 接口有一个 subList 方法,可以便捷的帮我们截取指定区间的元素。

java
/**
 * @param fromIndex 要截取的起始索引
 * @param toIndex 要截取的结束索引(不包含此索引)
 * @return 返回列表中指定范围的视图(对它的修改会影响到原有的 List,同样,对 List 的修改也会影响到 它)
 */
List<E> subList(int fromIndex, int toIndex)
java
/**
 * 原数组拆分成指定数量的数组
 * @param sourceList 原数组
 * @param n 指定数量
 * @param <T> 数组元素类型
 * @return 指定数量的数组
 */
private static <T> List<List<T>> averageAssignList(List<T> sourceList, int n) {
    ArrayList<List<T>> lists = new ArrayList<>();

    int size = sourceList.size();
    int count = size / n;
    int remainder = size % n;

    int offset = 0;
    for (int i = 0; i < n; i++) {
        List<T> list;
        if (remainder > 0) {// 数组元素不能被均等拆分
            list = sourceList.subList(i * count + offset, (i + 1) * count + (offset + 1));
            offset++;
            remainder--;
        } else {// 数组元素可以被均等拆分
            list = sourceList.subList(i * count + offset, (i + 1) * count + offset);
        }
        lists.add(list);
    }
    return lists;

}

测试

java
public static void main(String[] args) {
    ArrayList<Integer> integers = new ArrayList<>();
    integers.add(1);
    integers.add(2);
    integers.add(3);
    integers.add(4);
    integers.add(5);
    integers.add(6);
    integers.add(7);
    integers.add(8);

    List<List<Integer>> lists = averageAssignList(integers, 3);
    System.out.println("数组元素不可以被均等拆分:" + lists);

    System.out.println("--------------------");

    integers.add(9);

    List<List<Integer>> lists1 = averageAssignList(integers, 3);
    System.out.println("数组元素可以被均等拆分:" + lists1);
}
数组元素不可以被均等拆分:[[1, 2, 3], [4, 5, 6], [7, 8]]
--------------------
数组元素可以被均等拆分:[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

完整代码

java
package study.helloworld.something4j._2020._04._16;

import java.util.ArrayList;
import java.util.List;

/**
 * 数组元素拆分到多个数组
 */
public class AverageAssign4Array {

    public static void main(String[] args) {
        ArrayList<Integer> integers = new ArrayList<>();
        integers.add(1);
        integers.add(2);
        integers.add(3);
        integers.add(4);
        integers.add(5);
        integers.add(6);
        integers.add(7);
        integers.add(8);

        List<List<Integer>> lists = averageAssignList(integers, 3);
        System.out.println("数组元素不可以被均等拆分:" + lists);

        System.out.println("--------------------");

        integers.add(9);

        List<List<Integer>> lists1 = averageAssignList(integers, 3);
        System.out.println("数组元素可以被均等拆分:" + lists1);
    }

    /**
     * 原数组拆分成指定数量的数组
     * @param sourceList 原数组
     * @param n 指定数量
     * @param <T> 数组元素类型
     * @return 指定数量的数组
     */
    private static <T> List<List<T>> averageAssignList(List<T> sourceList, int n) {
        ArrayList<List<T>> lists = new ArrayList<>();

        int size = sourceList.size();
        int count = size / n;
        int remainder = size % n;

        int offset = 0;
        for (int i = 0; i < n; i++) {
            List<T> list;
            if (remainder > 0) {// 数组元素不能被均等拆分
                list = sourceList.subList(i * count + offset, (i + 1) * count + (offset + 1));
                offset++;
                remainder--;
            } else {// 数组元素可以被均等拆分
                list = sourceList.subList(i * count + offset, (i + 1) * count + offset);
            }
            lists.add(list);
        }
        return lists;

    }
}

Released under the MIT License.