LeetCode链接:Check Array Formation Through Concatenation
力扣链接:能否连接形成数组
题目描述:
给你一个整数数组 arr ,数组中的每个整数 互不相同 。另有一个由整数数组构成的数组 pieces,其中的整数也 互不相同 。
请你以任意顺序连接pieces 中的数组以形成 arr 。但是,不允许 对每个数组 pieces[i] 中的整数重新排序。
如果可以连接 pieces 中的数组形成 arr ,返回 true ;否则,返回 false
提示:
1 <= pieces.length <= arr.length <= 100
sum(pieces[i].length) == arr.length
1 <= pieces[i].length <= arr.length
1 <= arr[i], pieces[i][j] <= 100 arr 中的整数互不相同
pieces 中的整数互不相同(也就是说,如果将 pieces扁平化成一维数组,数组中的所有整数互不相同)
题目解读:
arr是一串整数, pieces里是一块一块的整数。 问是否能够调整pieces块的顺序,让得到整数序列和arr里是一样的。
pieces块之间可以交换顺序, 块内部不能交换。
不仅要保证pieces块里的整数能拼成arr里的整数, 还得要顺序一致。
思路分析
暴力方式
因为题目里已经说了arr和pieces里的整数个数相等,而且都没有重复。 所以直接拿pieces里的每一块(piece_one)开始遍历。
for piece_one in pieces:
for num in piece_one:
在arr里查找这个num的下标idx
if (没有查找到下标)
return false; // 说明这个num不存在, 那么一定不能拼接成arr了.
if (同一个piece_one里的数在arr里对应的下标不是连续的)
return false; // 说明piece_one里整数顺序和arr不一样,由于一个piece_one里的顺序不能交换, 所以返回false。
return true;
采用map避免暴力查找
上面的暴力方式也可以从arr开始遍历。 然后查找该整数在pieces里的哪一块(piece_one), 然后再遍历块内部的整数。
这里可以用一个map来存储pieces里的块,用于加快查找pieces中的块。 key为块中第一个整数,value为该块。
class Solution {
public:
bool canFormArray(vector<int>& arr, vector<vector<int>>& pieces) {
std::map<int, std::vector<int>> map;
for (int i = 0; i < pieces.size(); ++i)
{
map[pieces[i][0]] = pieces[i]; // key为块中第一个整数,value为该块
}
int i = 0;
while (i < arr.size())
{
int num = arr[i];
auto iter = map.find(num);
if (iter == map.end()) // 不在map中,说明piece里没有这个数,那就不能拼接成功
return false;
auto piece_one = map[num];
for (int j = 1; j < piece_one.size(); ++j)
{
if (piece_one[j] != arr[i+j]) // 不相等说明顺序不一样,那就不能拼接成功
return false;
}
i += piece_one.size(); // i往前走块的长度
}
return true;
}
};
用vector替代map
map仅仅是为了加快查找piece里的块,题目里提到数字最大为100,所以这里可以通过数组来查找块。
class Solution {
public:
bool canFormArray(vector<int>& arr, vector<vector<int>>& pieces) {
std::vector<int> pos(101, -1); // 长度为101的数组。 -1代表该数组下标没有被块占用。
for (int i = 0; i < pieces.size(); ++i)
{
int first_num = pieces[i][0];
pos[first_num] = i; // 填充pos数组下标,下标位置为【块内第一个元素的值】,内容为该块在pieces里的位置。
}
int i = 0;
while (i < arr.size()) {
int idx = pos[arr[i]];
if (idx == -1) // -1表示该下标位置没有被占用,即pieces里没有arr[i]这个值。(这里需要理解一下)
return false;
auto piece_one = pieces[idx]; // idx就是arr[i]对应的块在pieces里的位置。
for (int j = 1; j < piece_one.size(); ++j)
{
if (piece_one[j] != arr[i+j])
return false;
}
i += piece_one.size();
}
return true;
}
};