Easy
题目描述
给你一个由不同整数组成的数组 arr 和一个整数数组的数组 pieces,其中 pieces 中的整数互不相同。你的目标是以任意顺序连接 pieces 中的数组来形成 arr。但是,你不允许对每个数组 pieces[i] 中的整数重新排序。
如果可以从 pieces 形成数组 arr,返回 true;否则,返回 false。
示例 1:
输入:arr = [15,88], pieces = [[88],[15]]
输出:true
解释:依次连接 [15] 和 [88]
示例 2:
输入:arr = [49,18,16], pieces = [[16,18,49]]
输出:false
解释:即使数字匹配,我们也不能重新排序 pieces[0]。
示例 3:
输入:arr = [91,4,64,78], pieces = [[78],[4,64],[91]]
输出:true
解释:依次连接 [91] 和 [4,64] 和 [78]
约束条件:
1 <= pieces.length <= arr.length <= 100sum(pieces[i].length) == arr.length1 <= pieces[i].length <= arr.length1 <= arr[i], pieces[i][j] <= 100arr中的整数是不同的pieces中的整数是不同的(即,如果我们将pieces展开为一维数组,该数组中的所有整数都是不同的)
解题思路
这道题的核心思路是验证能否通过拼接 pieces 中的子数组来重构原数组 arr。
思路分析:
我们可以使用哈希表来建立映射关系。关键观察是:每个 piece 的第一个元素是该 piece 的唯一标识,因为所有数字都是不同的。
解法一(推荐):哈希表映射法
- 用哈希表存储每个 piece 的第一个元素到整个 piece 的映射
- 遍历 arr,对于每个位置:
- 如果当前元素是某个 piece 的起始元素,找到对应的 piece
- 验证从当前位置开始的子序列是否与该 piece 完全匹配
- 如果匹配,跳过整个 piece 的长度;如果不匹配,返回 false
解法二:直接匹配法 对于 arr 中的每个位置,尝试在 pieces 中找到以当前元素开始的 piece,然后验证是否完全匹配。
时间复杂度上两种解法相似,但哈希表法在查找 piece 时更高效。
代码实现
class Solution {
public:
bool canFormArray(vector<int>& arr, vector<vector<int>>& pieces) {
unordered_map<int, vector<int>> map;
for (auto& piece : pieces) {
map[piece[0]] = piece;
}
int i = 0;
while (i < arr.size()) {
if (map.find(arr[i]) == map.end()) {
return false;
}
vector<int>& piece = map[arr[i]];
for (int j = 0; j < piece.size(); j++) {
if (i >= arr.size() || arr[i] != piece[j]) {
return false;
}
i++;
}
}
return true;
}
};
class Solution:
def canFormArray(self, arr: List[int], pieces: List[List[int]]) -> bool:
piece_map = {piece[0]: piece for piece in pieces}
i = 0
while i < len(arr):
if arr[i] not in piece_map:
return False
piece = piece_map[arr[i]]
for j in range(len(piece)):
if i >= len(arr) or arr[i] != piece[j]:
return False
i += 1
return True
public class Solution {
public bool CanFormArray(int[] arr, int[][] pieces) {
var pieceMap = new Dictionary<int, int[]>();
foreach (var piece in pieces) {
pieceMap[piece[0]] = piece;
}
int i = 0;
while (i < arr.Length) {
if (!pieceMap.ContainsKey(arr[i])) {
return false;
}
var piece = pieceMap[arr[i]];
for (int j = 0; j < piece.Length; j++) {
if (i >= arr.Length || arr[i] != piece[j]) {
return false;
}
i++;
}
}
return true;
}
}
var canFormArray = function(arr, pieces) {
const pieceMap = new Map();
for (const piece of pieces) {
pieceMap.set(piece[0], piece);
}
let i = 0;
while (i < arr.length) {
if (!pieceMap.has(arr[i])) {
return false;
}
const piece = pieceMap.get(arr[i]);
for (let j = 0; j < piece.length; j++) {
if (i >= arr.length || arr[i] !== piece[j]) {
return false;
}
i++;
}
}
return true;
};
复杂度分析
| 复杂度 | 大小 |
|---|---|
| 时间复杂度 | O(n) |
| 空间复杂度 | O(m) |
其中 n 是数组 arr 的长度,m 是 pieces 数组的长度。时间复杂度为 O(n) 因为我们只需要遍历 arr 一次,空间复杂度为 O(m) 用于存储哈希表。