leetcode
leetcode 1751 ~ 1800
将一维数组转变成二维数组

将一维数组转变成二维数组

难度:

标签:

题目描述

给你一个下标从 0 开始的一维整数数组 original 和两个整数 m 和  n 。你需要使用 original 中 所有 元素创建一个 m 行 n 列的二维数组。

original 中下标从 0 到 n - 1 (都 包含 )的元素构成二维数组的第一行,下标从 n 到 2 * n - 1 (都 包含 )的元素构成二维数组的第二行,依此类推。

请你根据上述过程返回一个 m x n 的二维数组。如果无法构成这样的二维数组,请你返回一个空的二维数组。

 

示例 1:

输入:original = [1,2,3,4], m = 2, n = 2
输出:[[1,2],[3,4]]
解释:
构造出的二维数组应该包含 2 行 2 列。
original 中第一个 n=2 的部分为 [1,2] ,构成二维数组的第一行。
original 中第二个 n=2 的部分为 [3,4] ,构成二维数组的第二行。

示例 2:

输入:original = [1,2,3], m = 1, n = 3
输出:[[1,2,3]]
解释:
构造出的二维数组应该包含 1 行 3 列。
将 original 中所有三个元素放入第一行中,构成要求的二维数组。

示例 3:

输入:original = [1,2], m = 1, n = 1
输出:[]
解释:
original 中有 2 个元素。
无法将 2 个元素放入到一个 1x1 的二维数组中,所以返回一个空的二维数组。

示例 4:

输入:original = [3], m = 1, n = 2
输出:[]
解释:
original 中只有 1 个元素。
无法将 1 个元素放满一个 1x2 的二维数组,所以返回一个空的二维数组。

 

提示:

  • 1 <= original.length <= 5 * 104
  • 1 <= original[i] <= 105
  • 1 <= m, n <= 4 * 104

代码结果

运行时间: 40 ms, 内存: 22.2 MB


/* 思路:
 1. 使用 Java Stream API 将数组切分为指定大小,并转换为二维数组。
 2. 同样需要首先检查 original 数组的元素数量是否满足 m * n 的要求。
*/

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Solution {
    public int[][] construct2DArray(int[] original, int m, int n) {
        if (original.length != m * n) {
            return new int[0][0];
        }
        
        List<int[]> resultList = IntStream.range(0, m)
            .mapToObj(i -> IntStream.range(0, n)
            .map(j -> original[i * n + j])
            .toArray())
            .collect(Collectors.toList());
        
        return resultList.toArray(new int[m][n]);
    }
}

解释

方法:

该题解首先检查给定的一维数组 original 是否可以被完整地转换为一个 m 行 n 列的二维数组。这是通过检查 original 的长度是否等于 m 乘以 n 来实现的。如果不等,表明不能完全填充二维数组,因此返回一个空数组。如果长度匹配,题解使用列表推导式来生成所需的二维数组。这通过分割 original,每 n 个元素为一组,生成新的子数组,每个子数组对应二维数组的一行。

时间复杂度:

O(len(original))

空间复杂度:

O(m * n)

代码细节讲解

🦆
题解中提到,如果original数组的长度不等于m乘以n时返回空数组,这种情况是否包括original长度大于m乘以n的情况?
是的,题解中提到的条件是如果original数组的长度不等于m乘以n,这包括了两种情况:长度小于m乘以n和长度大于m乘以n。在任何一种情况下,original数组都不能被完美地转换成一个m行n列的二维数组,因此会返回一个空数组。
🦆
在构建二维数组时,使用的列表推导式`[original[i*n:(i+1)*n] for i in range(m)]`具体是如何工作的?它是如何确保每次切片都正确无误地获取到应有的元素?
列表推导式`[original[i*n:(i+1)*n] for i in range(m)]`通过迭代从0到m-1的每个整数i来工作。对于每个i,计算从`i*n`到`(i+1)*n`的切片,这正好截取original数组中的n个元素。因为i从0开始,第一次切片截取的是从索引0到n-1的元素,下一次从n到2n-1,依此类推,直到i=m-1。这种方式确保了每次切片都能正确无误地获取到应有的n个元素,并且每个切片对应二维数组的一行。
🦆
如果original数组为空,但m和n不为零,题解中的方法是否仍然适用?返回的结果是否符合题目要求?
如果original数组为空且m和n不为零,按照题解中的逻辑,因为0(original的长度)不等于m乘以n(除非m和n也都是0),所以会返回一个空数组。这符合题目要求,因为一个非空的m乘以n矩阵不能由一个空的original数组构造。
🦆
在列表推导式中使用了切片操作,这种方式在处理非常大的数组时性能如何?是否有更优的处理方式?
在处理非常大的数组时,使用切片操作可能会引起性能问题,因为每次切片操作都会创建原数组的一个新子数组,这涉及到数据的复制。如果数组非常大,这种复制会消耗大量的时间和内存。更优的处理方式可能包括使用生成器来延迟加载数据或者直接操作原数组的索引而不复制它们,从而避免大量的内存使用和提高性能。

相关问题