1640. 能否连接形成数组[暴力][哈希表]

题解

暴力法

很容易想到,如果需要重新连接pieces构成arr,则需要遍历arr中的元素arr[idx],在pieces[i]中找到一个满足arr[idx] == pieces[i][0]的下标i

  • 如果没有找到该下标i,则肯定无法重新连接称为arr,因为pieces[i]中的元素是不可重新排序的,直接返回false即可;
  • 若找到了该下标i,则仍需要去遍历pieces[i]中的元素,使得pieces[i][0]...pieces[i][n-1]arr[idx]...arr[idx+n-1]的元素和顺序均相同,其中n = pieces[i].length。若存在其中的某一个元素不同,则可直接返回false

依次遍历arr中的元素,直至idx == arr.length,即arr中的元素被遍历完,则说明其可以被pieces重排后构成,返回true

代码如下:

public class Solution {
    //纯暴力解法
    public boolean canFormArray(int[] arr, int[][] pieces) {
        int idx = 0;   //指向arr中的数,arr[0] ... arr[idx-1]的数都能够通过pieces拼接而成
        int i = 0;
        while(idx < arr.length){
            //去pieces中找arr[idx]
            for (i=0; i < pieces.length; i++) {
                if (pieces[i][0] == arr[idx]){
                    idx++;
                    //吧pieces[i]遍历完
                    for (int j = 1; j < pieces[i].length; j++, idx++) {
                        //无法遍历完,说明顺序有问题,直接返回false
                        if (pieces[i][j] != arr[idx]){
                            return false;
                        }
                    }
                    // 当前pieces[i]可以构成arr中的一部分,重新寻找下一个arr[idx]
                    break;
                }
            }
            //遍历完一轮没有找到arr[idx] == pieces[i][0]的下标i
            if (i == pieces.length){
                return false;
            }
        }

        return true;
    }
}

哈希表

从上面的分析中可以看出,我们需要在pieces中找到一个满足arr[idx] == pieces[i][0]的下标i,在暴力方法中是通过循环遍历来得到该下标i的,这比较耗时。

我们需要注意到pieces扁平化后所有元素都是不相同的,因此我们可以利用哈希表来存储pieces[i][0]与其下标i的映射关系,从而提升搜索的时间。

代码实现如下:

public class Solution1640v1 {
    public boolean canFormArray(int[] arr, int[][] pieces) {
        Map<Integer, Integer> map = new HashMap<>();
        int idx = 0;
        //需要按顺序遍历arr, 然后去pieces中寻找是否存在满足当前顺序的pieces[i]
        //因此map中应该存放的是pieces[i][0]的下标志
        for (int i = 0; i < pieces.length; i++) {
            map.put(pieces[i][0], i);
        }

        while(idx < arr.length){
            Integer i = map.get(arr[idx]);
            if (i == null){
                //说明pieces[i]中没有以arr[idx]开头的数,无法构成arr,直接返回false
                return false;
            }
            int[] piece = pieces[i];
            //arr[idx] == piece[0] 已经成立了,继续往下判断
            idx++;
            for (int j = 1; j < piece.length; j++, idx++) {
                if (arr[idx] != piece[j]){
                    //顺序不同,无法构成arr,直接返回
                    return false;
                }
            }

        }
        return true;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值