LeetCode 1640: Check Array Formation Through Concatenation(能否连接形成数组)

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;
	}
};

 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值