首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

两个数组的交集,O(n),就地,只有恒定数量的额外内存

基础概念

两个数组的交集是指两个数组中共有的元素组成的集合。通常情况下,我们需要找出两个数组中都存在的元素,并且结果中每个元素只出现一次。

相关优势

  • 时间复杂度:O(n)的时间复杂度意味着算法在处理大数据集时效率很高。
  • 空间复杂度:只使用恒定数量的额外内存,意味着算法的空间效率也很高。

类型

  • 暴力解法:通过两层循环遍历两个数组,时间复杂度为O(n^2),不满足题目要求。
  • 哈希表:使用哈希表存储一个数组的元素,然后遍历另一个数组检查元素是否在哈希表中,时间复杂度为O(n),但需要额外的空间。
  • 双指针:如果两个数组已经排序,可以使用双指针方法找到交集,时间复杂度为O(n),且只需要恒定数量的额外空间。

应用场景

  • 数据分析:在数据分析中,经常需要找出多个数据集中的共同特征或元素。
  • 推荐系统:在推荐系统中,可能需要找出用户之间的共同兴趣点。
  • 数据库查询优化:在数据库查询中,可以通过找出多个表的交集来优化查询结果。

问题与解决方案

假设我们有两个已排序的数组nums1nums2,我们需要找到它们的交集,并且要求空间复杂度为O(1)(即就地操作)。

问题

如何在不使用额外空间的情况下,找到两个已排序数组的交集?

原因

如果数组未排序,直接找交集通常需要使用哈希表,这会引入额外的空间复杂度。即使是已排序的数组,直接使用双指针法也需要额外的空间来存储结果。

解决方案

我们可以使用双指针法,并且在原数组上进行操作,以满足空间复杂度为O(1)的要求。具体步骤如下:

  1. 初始化两个指针ij分别指向nums1nums2的起始位置。
  2. 初始化一个变量k用于记录结果数组的位置。
  3. 比较nums1[i]nums2[j]
    • 如果相等,则将该元素放入结果数组,并移动两个指针。
    • 如果nums1[i]小于nums2[j],则移动指针i
    • 如果nums1[i]大于nums2[j],则移动指针j
  • 重复步骤3,直到任一数组遍历完毕。

示例代码

代码语言:txt
复制
def intersect(nums1, nums2):
    i, j = 0, 0
    k = 0
    while i < len(nums1) and j < len(nums2):
        if nums1[i] == nums2[j]:
            # 避免重复元素
            if k == 0 or nums1[k-1] != nums1[i]:
                nums1[k] = nums1[i]
                k += 1
            i += 1
            j += 1
        elif nums1[i] < nums2[j]:
            i += 1
        else:
            j += 1
    return nums1[:k]

# 示例
nums1 = [1, 2, 2, 1]
nums2 = [2, 2]
print(intersect(nums1, nums2))  # 输出: [2, 2]

参考链接

LeetCode 350. 两个数组的交集 II

通过上述方法,我们可以在O(n)的时间复杂度和O(1)的空间复杂度内找到两个已排序数组的交集。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

一文读懂比BitMap有更好性能的Roaring Bitmap

仅仅是因为当数据块中的整数数量超过这个值之后,bitmap将比数组的内存使用率更高。 ? 4.为了检查32位整数x是否存在,我们首先使用二进制搜索查找对应于x/2^16^ 的容器。...计算两个数组容器的交集时也是采取二分查找(要求数组中数值有序)。5.两个Roaring bitmap之间可以通过AND和OR位操作快速进行交集和并集计算。...与未压缩的bitmap相比,这些来自BBC的压缩格式尽管减少了内存的使用,但是它们具有较慢的随机访问速度。也就是说,检查或更改第i位值是一个O(n)时间复杂度的操作。...容器和动态数组带来的开销意味着我们的内存使用可以超过16位/整数。但是,只要容器的数量与整型数的总数相比很小,我们就不应该使用超过16位/整型的容器。我们假设容器的数量远远少于整数的范围。...只有两个例外: •我们只将1985年9月的数据用于天气数据集(其他人在[16]之前使用过的一种方法),否则它对于我们的测试环境来说太大了。

9.6K20

可视化详解,一文搞懂 10 大排序算法

就像冒泡排序一样,它的最坏情况和平均情况时间复杂度是 O(n^2) 。但与冒泡排序不同的是, 插入排序可用于对数据集进行就地排序,这意味着它不需要额外的内存来存储中间结果。...• 它需要很少的额外内存,因为它对数组进行就地排序。 • 它易于实施并且被广泛理解。 • 它很容易地并行化。...Shell 排序的优点 • 它是插入排序的改进版本,因此易于理解和实现。 • 对于许多输入数据序列,它的时间复杂性优于 O(n^2)。 • 这是一种就地排序算法,这意味着它不需要额外的内存。...• 就地排序 Shell 排序不需要额外的内存来对输入进行排序,这使得它在内存有限或不需要额外内存使用的情况下非常有用。...其他用途包括: • 对内存有限的数据进行排序 它只需要恒定数量的额外内存来执行排序,这使得它在内存使用受限的情况下很有用。

71320
  • 算法和数据结构:归并排序

    整个合并排序可以用如下递归式表示: D(N)=2D(N/2)+N,N>1; D(N)=0,N=1; (当N=1时,数组只有1个元素,已排好序,时间为0) 因为在分治算法中经常会用到递归式,所以在CLRS...这里简单的列举两种证明该递归式时间复杂度为O(nlgn)的方法: Prof1:处于方便性考虑,我们假设数组N为2的整数幂,这样根据递归式我们可以画出一棵树: ?...合并排序需要额外的长度为N的辅助空间来完成排序 如果对长度为N的序列进行排序需要的额外空间,认为就是就地排序(in place排序)也就是完成该排序操作需要较小的,固定数量的额外辅助内存空间...之前学习过的选择排序,插入排序,希尔排序都是原地排序。 但是在合并排序中,我们要创建一个大小为N的辅助排序数组来存放初始的数组或者存放合并好的数组,所以需要长度为N的额外辅助空间。...当然也有前人已经将合并排序改造为了就地合并排序,但是算法的实现变得比较复杂。 需要额外N的空间来辅助排序是合并排序的最大缺点,如果在内存比较关心的环境中可能需要采用其他算法。

    39530

    vector与deque的比较

    1. vector与deque vector与动态数组相同,能够在插入或删除元素时自动调整自身大小,其存储由容器自动处理,vector通常占用多于静态数组的空间,因为要分配更多的内存以管理将来的增长,...在每次插入元素的时,仅当额外内存耗尽时触发重新分配。...O(1) ,但当额外内存耗尽的时候,需要重新分配,此时重新分配,是需要单独再申请一份更大空间,把vector原有的元素重新放到新申请的空间上,再完成尾部插入,此时涉及到了新空间的申请、所有元素的移动和旧空间的释放...删除的时间复杂度为插入位置与到vector尾部距离成线性 O(n) 。.../末尾删除元素均摊常数 O(1) 常数 O(1) 随机插入/随机删除元素与到vector结尾的距离成线性 O(n) 线性 O(n) vector重分配在性能上是有开销的,如果在使用之前元素的数量已知,那么可以使用

    35210

    数据结构与算法 - 时间复杂度与空间复杂度

    前言 通常,对于一个给定的算法,我们首先要验证算法的正确性, 其次主要从算法的执行时间和所需要占用的存储空间两个方面衡量一个算法的优劣。...【2】计算基本语句的执行次数的数量级; 只需计算基本语句执行次数的数量级,这就意味着只要保证基本语句执行次数的函数中的最高次幂正确即可,可以忽略所有低次幂和最高次幂的系数。这样能够简化算法分析。.../*执行一次*/ 执行时间恒定的算法,我们称之为具有O(1)的时间复杂度,又叫常数阶。...对于分支结构而言,无论是真,还是假,执行的次数都是恒定的, 不会随着n 的变大而发生变化,所以单纯的分支结构(不包含在循环结构中),其时间复杂度也是0(1)。...这样,所谓的判断某一年是否是闰年, 就变成了查找这个数组的某一项的值是多少的问题。此时,我们的运算是最小化了, 但是硬盘上或者内存中需要存储这2050个0和1。

    2.3K20

    代码面试

    两个指针在排序数组或链接列表中搜索对时通常很有用;例如,当您必须将数组的每个元素与其他元素进行比较时。 需要两个指针,因为只有一个指针,您将不得不不断地循环遍历数组以找到答案。...用单个迭代器来回进行此操作对于时间和空间复杂度而言效率低下-一种称为渐近分析的概念。尽管使用1个指针的强力或幼稚的解决方案将起作用,但它将产生类似于O(n²)的东西。...您可以尝试将数字放置在正确的索引中,但这会导致O(n ^ 2)的复杂度不是最优的,因此是循环排序模式。 [图片上传失败......通常,约束是您需要就地执行此操作,即使用现有的节点对象而不使用额外的内存。这是上面提到的模式有用的地方。...如何确定何时使用此模式: 如果要求您在不使用额外内存的情况下反向链接列表 链表模式就地反转的问题: 撤消子列表(中) 反转每个K元素子列表(中) 模式七:树的宽度优先搜索 此模式基于广度优先搜索(BFS

    1.8K31

    各种排序算法的总结和比较

    1 快速排序(QuickSort) 快速排序是一个就地排序,分而治之,大规模递归的算法。从本质上来说,它是归并排序的就地版本。快速排序可以由下面四步组成。...2 归并排序(MergeSort) 归并排序先分解要排序的序列,从1分成2,2分成4,依次分解,当分解到只有1个一组的时候,就可以排序这些分组,然后依次合并回原来的序列中,这样就可以排序所有数据。...合并排序比堆排序稍微快一点,但是需要比堆排序多一倍的内存空间,因为它需要一个额外的数组。 3 堆排序(HeapSort) 堆排序适合于数据量非常大的场合(百万数据)。...它通过一趟又一趟地比较数组中的每一个元素,使较大的数据下沉,较小的数据上升。它是O(n^2)的算法。...排序法 平均时间 最差情形 稳定度 额外空间 备注 冒泡 O(n2) O(n2) 稳定 O(1) n小时较好 交换 O(n2) O(n2) 不稳定 O(1) n小时较好 选择 O(n2) O(n2) 不稳定

    1.6K60

    LeetCode-14. 最长公共前缀(java)

    题目不是要找出所有元素的​​最长公共前缀​​么,那说明得每个元素是否存在这样的一个交集。         ...做法就是:遍历集合中的每个元素,先定义一个公共前缀str,然后找出它与公共前缀str的交集,然后将交集部分再赋值给公共前缀str,依次循环下去。最终的公共前缀str就是算法想要的答案。...其中m 是字符串数组中的字符串的平均长度,n 是字符串的数量。最坏情况下,字符串数组中的每个字符串的每个字符都会被比较一次。 空间复杂度:O(1)。使用的额外空间复杂度为常数。...2、纵向扫描法之leetcode提交运行结果截图如下: 纵向扫描法复杂度分析: 时间复杂度:O(mn)。其中 mm 是字符串数组中的字符串的平均长度,n是字符串的数量。...最坏情况下,字符串数组中的每个字符串的每个字符都会被比较一次。 空间复杂度:O(1)。使用的额外空间复杂度为常数。        ... ...

    35310

    权重随机分配器

    假如有一个数组,需要随机从该数组中选择一个元素输出。只需生成一个介于 0 和集合长度减 1 之间的随机数,并将其用作集合中的索引(如果它是数组)以获取随机条目。...换句话说,如果我们生成十个随机选择,我们希望其中两个是 A,其中四个是 B,等等(这当然不会发生在只有十个随机选择的情况下)。...如果我们想降低一个选择的权重,我们只需扫描列表并根据需要删除尽可能多的选择。增加权重或添加新选项甚至更简单,因为我们可以在列表末尾添加任意数量的选项。...我们的初始集合越大,这变得越慢。选择的复杂度是 O(n),其中 n 是集合中元素的数量。...每个方案都有自己的优点和缺点。如果目标是快速选择,且您的元素数量小,权重不是很大,则使用扩展方案。如果需要降低内存使用,则不要使用扩展。

    1.5K60

    SHELL(bash)脚本编程八:技巧

    这样处理能充分发挥服务器性能,但它的一个问题是,如果文件较大,对内存的消耗也会很大。 一种解决方案是: #!...另外,tee命令分发的速率是恒定的,所以只能按处理命令中最慢的速率分发,它们的输出将争用同一个管道,一定条件下,有可能造成死锁。 另一种解决方案: #!.../bin/bash #处理函数,假设该函数的处理结果有且只有一个值 sth_todo() { #需要对第一个参数处理的命令 some_command $1 } #文件数组,也可以是其他待处理数据...5、数组交、并、差集 假定有需要取两个数组的交集(或并集、差集),简单的做法无非是两个循环对比两个数组中的每个值,取得相同的部分: #!...#重置IFS值 IFS=$'\n' #交集 grep -xf <(echo "${list_1[*]}") <<<"${list_2[*]}" #并集 sort -u <<EOF ${ip[*]} ${

    63820

    【算法千题案例】⚡️每日LeetCode打卡⚡️——52.两个数组的交集

    ---- 原题样例:两个数组的交集 给定两个数组,编写一个函数来计算它们的交集。...假设数组 nums1 和 nums2 的长度分别是 m和 n,则遍历数组 nums1 需要 O(m) 的时间,判断 nums1 中的每个元素是否在数组 nums2 中需要 O(n) 的时间,因此总时间复杂度是...内存消耗:38.7 MB,在所有 Java 提交中击败了28.49%的用户 复杂度分析 时间复杂度:O( m+n ) 空间复杂度:O( m+n ) ---- Java方法二:排序 + 双指针 如果两个数组是有序的...,则可以使用双指针的方法得到两个数组的交集。...可以预见的是加入答案的数组的元素一定是递增的,为了保证加入元素的唯一性,我们需要额外记录变量 pre 表示上一次加入答案数组的元素。 初始时,两个指针分别指向两个数组的头部。

    39530

    【算法千题案例】⚡️每日LeetCode打卡⚡️——53.两个数组的交集 II

    ---- 原题样例:两个数组的交集 给定两个数组,编写一个函数来计算它们的交集。...对于一个数字,其在交集中出现的次数等于该数字在两个数组中出现次数的最小值。...内存消耗:38.8 MB,在所有 Java 提交中击败了5.86%的用户 复杂度分析 时间复杂度:O( m+n ) 空间复杂度:O( m+n ) ---- Java方法二:排序 + 双指针 如果两个数组是有序的...,则可以使用双指针的方法得到两个数组的交集。...可以预见的是加入答案的数组的元素一定是递增的,为了保证加入元素的唯一性,我们需要额外记录变量 pre 表示上一次加入答案数组的元素。 初始时,两个指针分别指向两个数组的头部。

    30320

    求两个有序数组合并后的中位数,最透讲解| 腾讯面试编程50题(三)

    并对归并排序可能不是很了解的同学,提供了图解归并排序的讲解。 题目 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。...请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。你可以假设 nums1 和 nums2 不会同时为空。...归并排序的空间复杂度为O(n),会占用内存。 总之,归并排序虽然比较占用内存,但却是一种效率高且稳定的算法。...总结 归并排序的时间复杂度,在最坏,最好和平均都是O(nlogn),这是效率,性能非常好的排序算法。 只不过它需要占用 O(n)的内存空间,如果数据量一旦很大,内存可能吃不消,这是它的弱点和致命伤。...而其他排序算法,比如快速排序,希尔排序,都是就地排序算法,它们不占用额外的内存空间。 不过,这个占用内存的弱点,可以改进为就地排序,大家感兴趣,可以查看一下。

    1.1K20

    求两个有序数组合并后的中位数,最透讲解| 腾讯面试编程50题(三)

    并对归并排序可能不是很了解的同学,提供了图解归并排序的讲解。 题目 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。...请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。你可以假设 nums1 和 nums2 不会同时为空。...归并排序的空间复杂度为O(n),会占用内存。 总之,归并排序虽然比较占用内存,但却是一种效率高且稳定的算法。...总结 归并排序的时间复杂度,在最坏,最好和平均都是O(nlogn),这是效率,性能非常好的排序算法。 只不过它需要占用 O(n)的内存空间,如果数据量一旦很大,内存可能吃不消,这是它的弱点和致命伤。...而其他排序算法,比如快速排序,希尔排序,都是就地排序算法,它们不占用额外的内存空间。 不过,这个占用内存的弱点,可以改进为就地排序,大家感兴趣,可以查看一下。 ----

    86620

    C++ 哈希的应用【位图】

    的 位图 结构,将 40 亿个数统统存进去(重复数据不影响),存储完毕后,直接利用 位图 的特性:极速查找(哈希映射),就可以在 O(1) 时间内解决问题 至于内存占用,UINT_MAX 大约相当于 512...位图 本质上就是一个 vector 的数组,不过此时使用的是 比特位 结构如下: //非类型模板参数,这里的含义是比特位的总个数 templateN> class bitset...,分别有 100 亿个整数(无序),我们只有 1 GB 内存,如何找到两个文件交集?...{1, 1, 2},交集中是没有重复值的,想要解决这个问题有两个方法: 初步得到交集后进行去重,就能得到最终的交集 判断该数是否为交集,如果是,记录数值后,把位图中的值给 reset,这样即使后续有重复的值...,也不会被纳入交集了 解决方案二(无内存空间限制的情况下):直接搞两个位图,把两个文件都读进去,然后同时遍历,通过 & 位运算求出交集就行了 这种方案很暴力,对空间要求较高,且每次遍历的时间都是恒定的(

    29630

    常见排序算法分析

    2.这样对数组的第0个数据到N-1个数据进行一次遍历后,最大的一个数据就“沉”到数组第N-1个位置。 3.N=N-1,如果N不为0就重复前面二步,否则排序完成。...2.快速排序 一趟快速排序的算法是:    1)、设置两个变量I、J,排序开始的时候I:=1,J:=N;    2)以第一个数组元素作为关键数据,赋值给X,即X:=A[1];    3)、从J开始向前搜索...合并排序比堆排序稍微快一点,但是需要比堆排序多一倍的内存空间,因为它需要一个额外的数组。 3 堆排序(HeapSort) 堆排序适合于数据量非常大的场合(百万数据)。...它通过一趟又一趟地比较数组中的每一个元素,使较大的数据下沉,较小的数据上升。它是O(n^2)的算法。...image.png 排序法 平均时间 最差情形 稳定度 额外空间 备注 冒泡 O(n2) O(n2) 稳定 O(1) n小时较好 交换 O(n2) O(n2) 不稳定 O(1) n小时较好 选择 O(n2

    76080

    极致高效的数据处理:位图、布隆过滤器与哈希切分的奇妙之旅

    内存占用合理,约 512 MB。 1.4 位图应用 题目1:给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件的交集?...哈希函数的数量 k 的最佳值可以通过以下公式估计: k=\frac{m}{n} \ln 2 其中: m 是位数组的大小。 n 是添加到布隆过滤器中的元素数量。...当 n 增加到接近或超过位数组的容量时,误判率会显著上升。为此,在设计布隆过滤器时通常会根据预计的元素数量 n 来设定适当的位数组大小 m 和哈希函数数量 k。 4....k 是哈希函数的数量。 n 是插入的元素数量。 e 是自然对数的底,约等于 2.718。 这个公式表示,当插入的元素数量 n 较大、位数组较小 m 较小时,误判率 P 会显著增大。...3.5 哈希切分的应用 题目1:给两个文件 A 和 B,分别有100亿个query,我们只有1G内存,如何找到两个文件交集?分别给出精确算法和近似算法。

    13210

    经典算法面试题目-设计算法移除字符串中重复的字符(1.3)

    设计算法并写出代码移除字符串中重复的字符,不能使用额外的缓存空间。注意: 可以使用额外的一个或两个变量,但不允许额外再开一个数组拷贝。 进一步地, 为你的程序写测试用例。...如果根本就不允许你再开一个数组,只能用额外的一到两个变量。...那么,你可以依次访问 这个数组的每个元素,每访问一个,就将该元素到字符串结尾的元素中相同的元素去掉( 比如置为’\0′).时间复杂度为O(n2 ),代码如下: void removeDuplicate(...,那么可以用一个数组来 表征每个字符的出现(假设是ASCII字符,则数组大小为256),这样的话只需要遍历一遍字符 串即可,时间复杂度O(n)。...,一样可以在O(n)的时间里移除重复字符,而且还不需要额 外开一个数组。

    43620
    领券