Java 中不使用额外空间合并两个排序数组2024年9月10日 | 阅读13分钟 我们有两个包含整数的数组。这两个数组都按升序排序。我们的任务是显示两个已排序数组的所有元素,以便所有元素都按升序显示。请注意,不允许使用任何额外的空间来存储元素。换句话说,程序的空间复杂度应始终为常数。 示例 1 输入 int inArr1[] = {1, 3, 7, 9, 15, 20} 输出 {1, 2, 3, 5, 7, 8, 9, 11, 14, 15, 16, 18, 19, 20} 解释 当我们将两个数组按升序合并时,得到上面的输出。 示例 2 输入 int inArr1[] = {-11, -5, -3, 1, 5, 15, 25, 30, 40, 45} 输出 {-30, -25, -19, -11, -10, -5, -3, -1, 1, 5, 7, 15, 20, 25, 29, 30, 35, 40, 45} 解释 当我们将两个数组按升序合并时,得到上面的输出。 简单方法:暴力法和排序如果允许使用额外空间,我们可以轻松创建一个大小等于输入数组大小之和的数组,然后使用两个指针将所有元素以升序放入构造的数组中。但是,问题说明不允许使用额外空间。因此,我们必须使用输入数组的空间。我们所要做的就是将前 m 个最小的元素放入第一个输入数组中。其余 n 个元素应放入第二个输入数组中。然后对第二个数组进行排序,因为第一个数组在此过程中将是已排序的。之后,使用 for 循环显示两个数组中的所有元素。请注意,这里的 m = 第一个输入数组的大小,n = 第二个输入数组的大小。 算法
现在观察以下程序。 文件名: MergeSortedArr.java 输出 The input arrays are: 1 3 7 9 15 20 2 5 8 11 14 16 18 19 After merging the sorted arrays, we get: 1 2 3 5 7 8 9 11 14 15 16 18 19 20 The input arrays are: -11 -5 -3 1 5 15 25 30 40 45 -30 -25 -19 -10 -1 7 20 29 35 After merging the sorted arrays, we get: -30 -25 -19 -11 -10 -5 -3 -1 1 5 7 15 20 25 29 30 35 40 45 复杂度分析:第一个数组 inArr1[] 以 O(m) 的时间遍历,对于 inArr1[] 中的每个元素,我们都遍历 inArr1[] 的其余位置以及 inArr2[] 的所有位置。因此,程序的总体时间复杂度为 O(m x (m + n))。该程序不使用额外空间。因此,程序的空间复杂度为 O(1)。 另一种方法:使用双指针和排序在这里,我们将 'm' 个最小的数字保留在 'inArr1[]' 中(可能已排序,也可能未排序),其余元素保留在 'inArr2[]' 中(可能已排序,也可能未排序)。我们分别使用两个指针 'p' = 0 和 'q' = 0 来遍历 'inArr1[]' 和 'inArr2[]'。如果 'inArr1[p]' 等于或大于 'inArr2[q]',则我们将 'inArr1[]' 的某个 'k' 位置的元素与 'inArr2[q]' 交换,并增加 'q',否则,我们增加 'p'。将 'inArr1[]' 中最大的元素替换是有意义的。因此,我们初始化 'k' = 'm - 1'。之后,我们在每次交换后减少 'k'。最后,我们对 'inArr1[]' 和 'inArr2[]' 进行排序。 算法
现在,观察以下实现。 文件名: MergeSortedArr1.java 输出 The input arrays are: 1 3 7 9 15 20 2 5 8 11 14 16 18 19 After merging the sorted arrays, we get: 1 2 3 5 7 8 9 11 14 15 16 18 19 20 The input arrays are: -11 -5 -3 1 5 15 25 30 40 45 -30 -25 -19 -10 -1 7 20 29 35 After merging the sorted arrays, we get: -30 -25 -19 -11 -10 -5 -3 -1 1 5 7 15 20 25 29 30 35 40 45 复杂度分析:我们以 O(m + n) 的时间遍历 'inArr1[]' 和 'inArr2[]',元素交换 Takes O(1) 时间。对 'inArr1[]' 和 'inArr2[]' 的排序分别需要 O(m x log(m)) 和 O(n x log(n)) 的时间。因此,上述程序的总体时间复杂度为 O(m + n + m x log(m) + n x log(n))。该程序的空间复杂度为 O(1),因为没有使用额外空间。 另一种方法:使用欧几里得除法引理在此方法中,我们将进行交换,而无需在最后对数组进行排序。我们将把最小的数字填充到最小的位置,而不是像方法 2那样将它们放在最后的位置(即,我们将从 'k' = 0 开始,而不是 'k' = 'm - 1')。但是,在这种情况下,'inArr1[]' 中的某个数字可能会被第二个数组 'inArr2[]' 中的某些数字替换。但是,很有可能它将在 'inArr1[]' 中的稍后位置被利用。因此,有必要提取最初位于位置 'k' 的数字,以防它先前被替换。 我们可以通过以下方式使用欧几里得引理 从数字 M = X * R + P,我们可以通过将 'M' 除以 'R' 来获得 'X',并通过将 'M' 对 'R' 取模来获得 'P'。 我们将 MAX = 109 + 1 选择为整个数组 'inArr1[]' 的 'R'。 我们使用两个指针 'p' 和 'q' 遍历 'inArr1[]' 和 'inArr2[]' 的元素。将位置初始化为 'k' = 0。我们检查 'inArr1[p]' 和 'inArr2[q]' 处最初放置的数字。我们比较它们,并将 'inArr1[k]' 或 'inArr2[k - m]' 增加最小的两个原始数字乘以 'MAX' 的乘积。如果来自 'inArr2[]' 的数字较小,则增加 'q'。否则,我们增加 'p'。 类似地,我们更新所有 'k' 从 0 到 'm + n - 1' 的值。 最后,我们遍历 'inArr1[]' 和 'inArr2[]' 并将所有数字除以 'R' 来获得合并后的数组。 算法
现在,让我们观察以下实现。 文件名: MergeSortedArr2.java 输出 The input arrays are: 1 3 7 9 15 20 2 5 8 11 14 16 18 19 After merging the sorted arrays, we get: 1 2 3 5 7 8 9 11 14 15 16 18 19 20 复杂度分析:在该程序中,两个输入数组都只被遍历一次。因此,程序的总时间复杂度为 O(m + n),其中 'm' 是输入数组 'inArr1[]' 的大小,'n' 是输入数组 'inArr2[]' 的大小。程序的空间复杂度与上一个程序相同。 注意:上述程序对于包含负数 的输入数组不起作用。下一个主题如何在 Java 中调用抽象类的具体方法 |
在本节中,我们将创建一个 Java 程序来显示从 1 到 100 的奇数。要学习 Java 奇数程序,您必须具备 Java for 循环和 if 语句的基本知识。我们可以使用不同的 Java 循环来显示奇数:使用...
阅读 3 分钟
悬空 else 问题是语言解释的歧义。在编程中,我们可以用以下两种形式编写条件执行的代码:if-then 形式 if-then-else 形式当我们处理嵌套的 if-else 语句时,该问题很少发生。这是一个歧义,不清楚...
阅读 2 分钟
在面向对象编程中,抽象被定义为隐藏用户不需要的细节(实现),而专注于基本信息(功能)。它提高了效率并降低了复杂性。在 Java 中,可以通过抽象类和抽象方法来实现抽象。抽象方法 在 Java 中,抽象方法是...
5 分钟阅读
尤其是在应用程序中,管理时间和日期是 Java 中一项非常常见的任务。JDK 8 包含时间包,其中包含用于处理时间和日期的类集。其中,LocalTime 类特别创建用于...
5 分钟阅读
构造函数与 方法在 Java 中的区别 构造函数 构造函数和 方法彼此不同。但是,构造函数用于初始化对象的 状态。构造函数还可以像 方法一样包含数据成员和成员函数。构造函数的数据成员和成员函数...
5 分钟阅读
树同构是树数据结构中的一个基本概念。如果可以通过交换某些节点的左右子节点将一个树转换为另一个树,则称两个树是同构的。这意味着树必须具有相同的结构,但位置...
5 分钟阅读
在 Java 中,函数和方法这两个术语通常可以互换使用,但它们之间存在细微差别:函数 是一个独立的代码块,用于执行特定任务。在 C 等过程式编程语言中,函数独立存在并按名称调用……
5 分钟阅读
逻辑计算和编程都依赖于 XOR(异或)运算。Java 中的 XOR 运算符提供了一种快速简便的方法来处理二进制数据和执行位运算。本节将全面介绍 Java 中 XOR 运算的细节,...
阅读 4 分钟
PMD 是一个开源的静态源代码分析器,用于报告应用程序代码中发现的问题。PMD 包含规则集的工作,并支持编写自定义规则的能力。PMD 不报告聚合错误,因为它只能处理高度结构化的源文件。问题...
5 分钟阅读
在 Java 中,Fork/Join 框架主要用于提供与并行处理和编程相关的功能,它通过将操作分解为更小的操作或指令来完成,然后利用可用核心进行处理...
阅读9分钟
我们请求您订阅我们的新闻通讯以获取最新更新。
我们提供所有技术(如 Java 教程、Android、Java 框架)的教程和面试问题
G-13, 2nd Floor, Sec-3, Noida, UP, 201301, India