持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情
一、题目描述:
给你一个整数数组 arr ,数组中的每个整数 互不相同 。另有一个由整数数组构成的数组 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 <= 100
- sum(pieces[i].length) == arr.length
- 1 <= pieces[i].length <= arr.length
- 1 <= arr[i], pieces[i][j] <= 100
- arr 中的整数 互不相同
- pieces 中的整数 互不相同(也就是说,如果将 pieces 扁平化成一维数组,数组中的所有整数互不相同)
二、思路分析:
深搜回溯的操作不多赘述,可以将数组分为"[已经通过片段连接的部分][未曾通过片段连接的部分]",搜索剩余片段中未曾使用的片段与"未曾通过片段连接部分"的开始部分进行比较,若成功,则将该片段置为NULL以表明此片段已经使用并更新"被片段连接部分"的索引值;然后继续搜索,搜索失败则回溯(还原该片段表明为未使用片段)。
对于题目中的限制条件"数组中的数字不重复",代表回溯是不必要的(因为片段的顺序已经固定,若剩余片段没有可以匹配的,代表无法对片段进行连接以构造arr数组),大家可以尝试去除回溯代码。这里使用回溯,可以解决本题可能的扩展:"数组中的数字可以重复",我是个懒人就不进行修改了。
三、AC 代码:
bool dfs(int *arr, int pos_a, int arrSize, int **pieces, int piecesSize, int *piecesColSize) {
if (pos_a == arrSize) return true;
for (int i=0; i<piecesSize; ++i) {
bool flag = true;
int *t = pieces[i];
if (!t) continue;
pieces[i] = NULL;
int pos_a1 = pos_a;
for (int j=0; j<piecesColSize[i]; ++j) {
if (arr[pos_a1++] != t[j]) {
flag = false;
break;
}
}
if (flag && dfs(arr, pos_a1, arrSize, pieces, piecesSize, piecesColSize)) return true;
pieces[i] = t;
}
return false;
}
bool canFormArray(int* arr, int arrSize, int** pieces, int piecesSize, int* piecesColSize){
int totalSize = 0;
for (int i=0; i<piecesSize; ++i) {
totalSize += piecesColSize[i];
}
if (totalSize != arrSize) return false;
return dfs(arr, 0, arrSize, pieces, piecesSize, piecesColSize);
}