通过连接另一个数组的子数组得到一个数组

该篇博客介绍了如何利用贪心算法和双指针技巧解决从给定数组nums中找到与二维数组groups顺序相同的不相交子数组的问题。通过遍历并比较groups和nums,确保子数组顺序正确且不相交,最终判断是否能找出所有满足条件的子数组。文章还提供了两种解题方法,包括贪心+双指针和KMP算法,详细阐述了每种方法的思路及时间、空间复杂度分析。
摘要由CSDN通过智能技术生成

通过连接另一个数组的子数组得到一个数组

给你一个长度为 n 的二维整数数组 groups ,同时给你一个整数数组 nums 。

你是否可以从 nums 中选出 n 个 不相交 的子数组,使得第 i 个子数组与 groups[i] (下标从 0 开始)完全相同,且如果 i > 0 ,那么第 (i-1) 个子数组在 nums 中出现的位置在第 i 个子数组前面。(也就是说,这些子数组在 nums 中出现的顺序需要与 groups 顺序相同)

如果你可以找出这样的 n 个子数组,请你返回 true ,否则返回 false 。

如果不存在下标为 k 的元素 nums[k] 属于不止一个子数组,就称这些子数组是 不相交 的。子数组指的是原数组中连续元素组成的一个序列。

示例 1:

输入:groups = [[1,-1,-1],[3,-2,0]], nums = [1,-1,0,1,-1,-1,3,-2,0]
输出:true
解释:你可以分别在 nums 中选出第 0 个子数组 [1,-1,0,1,-1,-1,3,-2,0] 和第 1 个子数组 [1,-1,0,1,-1,-1,3,-2,0] 。
这两个子数组是不相交的,因为它们没有任何共同的元素。
示例 2:

输入:groups = [[10,-2],[1,2,3,4]], nums = [1,2,3,4,10,-2]
输出:false
解释:选择子数组 [1,2,3,4,10,-2] 和 [1,2,3,4,10,-2] 是不正确的,因为它们出现的顺序与 groups 中顺序不同。
[10,-2] 必须出现在 [1,2,3,4] 之前。
示例 3:

输入:groups = [[1,2,3],[3,4]], nums = [7,7,1,2,3,4,7,7]
输出:false
解释:选择子数组 [7,7,1,2,3,4,7,7] 和 [7,7,1,2,3,4,7,7] 是不正确的,因为它们不是不相交子数组。
它们有一个共同的元素 nums[4] (下标从 0 开始)。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/form-array-by-concatenating-subarrays-of-another-array

方法一:贪心+双指针

class Solution:
    def canChoose(self, groups: List[List[int]], nums: List[int]) -> bool:
        n=0
        ans=[False]*len(groups)
        for i in range(len(groups)):
            for j in range(n,len(nums)):
                if groups[i]!=nums[j:j+len(groups[i])]:
                    n=n+1
                if groups[i]==nums[j:j+len(groups[i])]:
                    n=n+len(groups[i])
                    ans[i]=True
                    break
        return all(ans)

解析

先定义指针n,表示数组nums下一次与groups[i]比较的位置;

定义元素全为False的数组ans,长度与groups的长度相同,ans[i]用来反映groups[i]是否满足题目条件;

套用两层for循环,对groups的子数组与nums进行匹配,匹配不成功,n+1,确保下一个子数组匹配时,头元素匹配的位置不会发生重复,造成失误;匹配成功时,n+该子数组的长度,下次匹配不会与已匹配元素产生交集,并且置ans[i]为True,退出当前循环,进行下一子数组的匹配;

全部匹配完成后,返回all(ans),如果ans元素全为true,all(ans)为true;否则为False;

复杂度

时间复杂度:O(n*m)
空间复杂度:O(1)

方法二:kmp算法

class Solution:
    def canChoose(self, groups: List[List[int]], nums: List[int]) -> bool:
        def Get_next(p,next):
            nums=len(p)
            for m in range(1,nums):
                k=0
                for i in range(0,m):

                    if p[0:i]==p[m-i:m]:
                        k=max(k,i)
                next.append(k)

        nums1=len(nums)
        i=0
        ans=[]
        for p in groups:
            nums2=len(p)
            next=[0]
            Get_next(p,next)
            j=0
            while i!=nums1 and j!=nums2:
                if nums[i]!=p[j]:
                    if j==0:
                        i+=1
                    j=next[j]
                    
                else:
                    i+=1
                    j+=1
            if j!=nums2:
                ans.append(False)
            else:
                ans.append(True)
        return all(ans)

解析

用kmp算法,首先写一个求模式串next[j]的函数,意思是模式串中当前指针所表示元素与主串的指针所表示元素不匹配时,模式串的指针应该回溯到的位置;

因为模式串的第一个元素不匹配时,不回溯;所以我们直接从第二个元素开始,用两层for循环遍历求每个元素的next[j],重点是 if p[0:i]==p[m-i:m]:k=max(k,i);m是未匹配成功时的指针位置,以模式串的首个元素开始的一个子序列p1,以m指示的上一个元素为末尾的一个子序列p2,p1=p2时,p1的末尾元素索引i-1最大时,取i作为指针回溯的位置;

定义一个数组ans用来记录groups的子数组的匹配情况;遍历groups的每个子数组,先用上面的函数求next[j],如果指针i,j都满足数组的长度限制,就对指针所指示元素进行匹配,如果相同,i,j指针同时后移;如果不同,j指针回溯到符合kmp算法的next[j]位置,与i指针进行匹配,直到j指针回溯到首元素位置时,i指针才向后移动;如果主串匹配完了,或模式串匹配完了,退出while循环;如果模式串匹配完,即j=nums2,则该子数组符合题目要求;反之,不符合;最后看ans数组是否都符合要求,解决需求。

复杂度

时间复杂度:O(m+∑ni),m为nums的长度;
空间复杂度:O(n),n为groups的长度

### 回答1: 可以使用数组的 concat 方法将一个数组添加到另一个数组的末尾: ```js let arr1 = [1, 2, 3]; let arr2 = [4, 5, 6]; let newArr = arr1.concat(arr2); console.log(newArr); // [1, 2, 3, 4, 5, 6] ``` 也可以使用展开运算符将一个数组展开并添加到另一个数组的末尾: ```js let arr1 = [1, 2, 3]; let arr2 = [4, 5, 6]; let newArr = [...arr1, ...arr2]; console.log(newArr); // [1, 2, 3, 4, 5, 6] ``` 如果想将一个数组添加到另一个数组的开头,可以使用数组的 unshift 方法: ```js let arr1 = [1, 2, 3]; let arr2 = [4, 5, 6]; arr2.unshift(...arr1); console.log(arr2); // [1, 2, 3, 4, 5, 6] ``` ### 回答2: 要把一个数组放在另一个数组里,可以使用JavaScript中的concat()方法或扩展运算符(...) 方法一:使用concat()方法 concat()方法用于连接两个或多个数组,并返回一个数组。可以将要添加的数组作为参数传递给concat()方法。 例如,如果我们有两个数组arr1和arr2,想要将arr2放在arr1的后面,可以使用concat()方法,如下所示: ```javascript let arr1 = [1, 2, 3]; let arr2 = [4, 5, 6]; let newArr = arr1.concat(arr2); console.log(newArr); // 输出: [1, 2, 3, 4, 5, 6] ``` 方法二:使用扩展运算符(...) JavaScript中的扩展运算符(...)可以用于将一个数组展开为多个参数,因此我们可以使用它来将一个数组放在另一个数组中。 例如,如果我们有两个数组arr1和arr2,想要将arr2放在arr1的后面,可以使用扩展运算符,如下所示: ```javascript let arr1 = [1, 2, 3]; let arr2 = [4, 5, 6]; let newArr = [...arr1, ...arr2]; console.log(newArr); // 输出: [1, 2, 3, 4, 5, 6] ``` 以上是两种常用的方法,将一个数组放在另一个数组里。无论选择哪种方法,都可以轻松地实现这个功能。 ### 回答3: 将一个数组放在另一个数组里,可以使用JavaScript中的push方法。通过push方法,可以将一个或多个元素添加到数组的末尾。 以下是一个示例代码: ```javascript var arr1 = [1, 2, 3]; // 第一个数组 var arr2 = [4, 5, 6]; // 第二个数组 arr1.push(arr2); // 将arr2数组作为一个元素放入arr1数组 console.log(arr1); // 输出结果为 [1, 2, 3, [4, 5, 6]] ``` 在示例代码中,我们通过push方法将arr2数组作为一个元素放入了arr1数组的末尾。最终,arr1数组的内容变为[1, 2, 3, [4, 5, 6]]。注意,arr2数组作为一个整体被添加到arr1数组中,而不是将arr2数组的每个元素逐个添加。 希望这个回答对您有帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XQK赵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值