我们给了两个排序数组。我们需要合并这两个数组,以使初始编号(完成排序后)在第一个数组中,而其余的数字在第二个数组中。 O(1)中允许有多余的空间。
例子:
Input: ar1[] = {10};
ar2[] = {2, 3};
Output: ar1[] = {2}
ar2[] = {3, 10}
Input: ar1[] = {1, 5, 9, 10, 15, 20};
ar2[] = {2, 3, 8, 13};
Output: ar1[] = {1, 2, 3, 5, 8, 9}
ar2[] = {10, 13, 15, 20}
如果允许我们使用额外的空间,则此任务很简单,并且为O(m + n)。但是,如果不允许有多余的空间,并且在最坏的情况下不到O(m * n)看起来不可能,那么它将变得非常复杂。尽管可以进行进一步的优化
这个想法是从ar2 []的最后一个元素开始,然后在ar1 []中搜索它。如果ar1 []中有一个更大的元素,则将ar1 []的最后一个元素移到ar2 []。为了使ar1 []和ar2 []保持排序,我们需要将ar2 []的最后一个元素放置在ar1 []中的正确位置。我们可以为此使用插入排序类型。
1.方法1
算法:
1) Iterate through every element of ar2[] starting from last
element. Do following for every element ar2[i]
a) Store last element of ar1[i]: last = ar1[i]
b) Loop from last element of ar1[] while element ar1[j] is
greater than ar2[i].
ar1[j+1] = ar1[j] // Move element one position ahead
j--
c) If any element of ar1[] was moved or (j != m-1)
ar1[j+1] = ar2[i]
ar2[i] = last
在上面的循环中,ar1 []和ar2 []中的元素始终保持排序状态。
下面是上述算法的实现。
C++
// C++ program to merge two sorted
// arrays with O(1) extra space.
#include
using namespace std;
// Merge ar1[] and ar2[] with O(1) extra space
void merge(int ar1[], int ar2[], int m, int n)
{
// Iterate through all elements
// of ar2[] starting from the last element
for (int i = n - 1; i >= 0; i--)
{
/* Find the smallest element greater than ar2[i].
Move all elements one position ahead till the
smallest greater element is not found */
int j, last = ar1[m - 1];
for (j = m - 2; j >= 0
&& ar1[j] > ar2[i]; j--)
ar1[j + 1] = ar1[j];
// If there was a greater element
if (j != m - 2 || last > ar2[i])
{
ar1[j + 1] = ar2[i];
ar2[i] = last;
}
}
}
// Driver program
int main()
{
int ar1[] = { 1, 5, 9, 10, 15, 20 };
int ar2[] = { 2, 3, 8, 13 };
int m = sizeof(ar1) / sizeof(ar1[0]);
int n = sizeof(ar2) / sizeof(ar2[0]);
merge(ar1, ar2, m, n);
cout << "After Merging nFirst Array: ";
for (int i = 0; i < m; i++)
cout << ar1[i] << " ";
cout << "nSecond Array: ";
for (int i = 0; i < n; i++)
cout << ar2[i] << " ";
return 0;
}
Java
// Java program program to merge two
// sorted arrays with O(1) extra space.
import java.util.Arrays;
class Test
{
static int arr1[] = new int[]{1, 5, 9, 10, 15, 20};
static int arr2[] = new int[]{2, 3, 8, 13};
static void merge(int m, int n)
{
// Iterate through all elements of ar2[] starting from
// the last element
for (int i=n-1; i>=0; i--)
{
/* Find the smallest element greater than ar2[i]. Move all
elements one position ahead till the smallest greater
element is not found */
int j, last = arr1[m-1];
for (j=m-2; j >= 0 && arr1[j] > arr2[i]; j--)
arr1[j+1] = arr1[j];
// If there was a greater element
if (j != m-2 || last > arr2[i])
{
arr1[j+1] = arr2[i];
arr2[i] = last;
}
}
}
// Driver method to test the above function
public static void main(String[] args)
{
merge(arr1.length,arr2.length);
System.out.print("After Merging nFirst Array: ");
System.out.println(Arrays.toString(arr1));
System.out.print("Second Array: ");
System.out.println(Arrays.toString(arr2));
}
}
Python3
# Python program to merge
# two sorted arrays
# with O(1) extra space.
# Merge ar1[] and ar2[]
# with O(1) extra space
def merge(ar1, ar2, m, n):
# Iterate through all
# elements of ar2[] starting from
# the last element
for i in range(n-1, -1, -1):
# Find the smallest element
# greater than ar2[i]. Move all
# elements one position ahead
# till the smallest greater
# element is not found
last = ar1[m-1]
j=m-2
while(j >= 0 and ar1[j] > ar2[i]):
ar1[j+1] = ar1[j]
j-=1
# If there was a greater element
if (j != m-2 or last > ar2[i]):
ar1[j+1] = ar2[i]
ar2[i] = last
# Driver program
ar1 = [1, 5, 9, 10, 15, 20]
ar2 = [2, 3, 8, 13]
m = len(ar1)
n = len(ar2)
merge(ar1, ar2, m, n)
print("After Merging \nFirst Array:", end="")
for i in range(m):
print(ar1[i] , " ", end="")
print("\nSecond Array: ", end="")
for i in range(n):
print(ar2[i] , " ", end="")
# This code is contributed
# by Anant Agarwal.
C#
// C# program program to merge two
// sorted arrays with O(1) extra space.
using System;
// Java program program to merge two
// sorted arrays with O(1) extra space.
public class Test
{
static int []arr1 = new int[]{1, 5, 9, 10, 15, 20};
static int []arr2 = new int[]{2, 3, 8, 13};
static void merge(int m, int n)
{
// Iterate through all elements of ar2[] starting from
// the last element
for (int i=n-1; i>=0; i--)
{
/* Find the smallest element greater than ar2[i]. Move all
elements one position ahead till the smallest greater
element is not found */
int j, last = arr1[m-1];
for (j=m-2; j >= 0 && arr1[j] > arr2[i]; j--)
arr1[j+1] = arr1[j];
// If there was a greater element
if (j != m-2 || last > arr2[i])
{
arr1[j+1] = arr2[i];
arr2[i] = last;
}
}
}
// Driver method to test the above function
public static void Main()
{
merge(arr1.Length,arr2.Length);
Console.Write("After Merging \nFirst Array: ");
for(int i =0; i< arr1.Length;i++){
Console.Write(arr1[i]+" ");
}
Console.Write("\nSecond Array: ");
for(int i =0; i< arr2.Length;i++){
Console.Write(arr2[i]+" ");
}
}
}
/*This code is contributed by 29AjayKumar*/
PHP
= 0; $i--)
{
/* Find the smallest element greater than ar2[i]. Move all
elements one position ahead till the smallest greater
element is not found */
$last = $ar1[$m-1];
for ($j = $m-2; $j >= 0 && $ar1[$j] > $ar2[$i]; $j--)
$ar1[$j+1] = $ar1[$j];
// If there was a greater element
if ($j != $m-2 || $last > $ar2[$i])
{
$ar1[$j+1] = $ar2[$i];
$ar2[$i] = $last;
}
}
}
// Driver program
$ar1 = array(1, 5, 9, 10, 15, 20);
$ar2 = array(2, 3, 8, 13);
$m = sizeof($ar1)/sizeof($ar1[0]);
$n = sizeof($ar2)/sizeof($ar2[0]);
merge($ar1, $ar2, $m, $n);
echo "After Merging \nFirst Array: ";
for ($i=0; $i<$m; $i++)
echo $ar1[$i] . " ";
echo "\nSecond Array: ";
for ($i=0; $i<$n; $i++)
echo $ar2[$i] ." ";
return 0;
?>
Javascript
C++
// CPP program for the above approach
#include
using namespace std;
// Function to merge two arrays
void merge(int arr1[], int arr2[], int n, int m)
{
int i = 0, j = 0, k = n - 1;
// Untill i less than equal to k
// or j is less tha m
while (i <= k and j < m) {
if (arr1[i] < arr2[j])
i++;
else {
swap(arr2[j++], arr1[k--]);
}
}
// Sort first array
sort(arr1, arr1 + n);
// Sort second array
sort(arr2, arr2 + m);
}
// Driver Code
int main()
{
int ar1[] = { 1, 5, 9, 10, 15, 20 };
int ar2[] = { 2, 3, 8, 13 };
int m = sizeof(ar1) / sizeof(ar1[0]);
int n = sizeof(ar2) / sizeof(ar2[0]);
merge(ar1, ar2, m, n);
cout << "After Merging \nFirst Array: ";
for (int i = 0; i < m; i++)
cout << ar1[i] << " ";
cout << "\nSecond Array: ";
for (int i = 0; i < n; i++)
cout << ar2[i] << " ";
return 0;
}
Java
// Java program for the above approach
import java.util.Arrays;
import java.util.Collections;
class GFG {
static int arr1[] = new int[] { 1, 5, 9, 10, 15, 20 };
static int arr2[] = new int[] { 2, 3, 8, 13 };
// Function to merge two arrays
static void merge(int m, int n)
{
int i = 0, j = 0, k = n - 1;
while (i <= k and j < m) {
if (arr1[i] < arr2[j])
i++;
else {
int temp = arr2[j];
arr2[j] = arr1[k];
arr1[k] = temp;
j++;
k--;
}
}
Arrays.sort(arr1);
Arrays.sort(arr2);
}
public static void main(String[] args)
{
merge(arr1.length, arr2.length);
System.out.print("After Merging \nFirst Array: ");
System.out.println(Arrays.toString(arr1));
System.out.print("Second Array: ");
System.out.println(Arrays.toString(arr2));
}
}
输出:
After Merging
First Array: 1 2 3 5 8 9
Second Array: 10 13 15 20
时间复杂度:最坏的情况是代码/算法的时间复杂度为O(m * n)。当ar1 []的所有元素都大于ar2 []的所有元素时,会发生最坏的情况。
插图:
<!—初始数组:
ar1 [] = {1,5,9,10,15,20};
AR2 [] = {2,3,8,13};
第一次迭代后:
ar1 [] = {1,5,9,10,13,15};
AR2 [] = {2,3,8,20};
// 20从ar1 []移至ar2 []
//将ar2 []中的13插入ar1 []中
在第二次迭代之后:
ar1 [] = {1,5,8,9,10,13};
AR2 [] = {2,3,15,20};
// 15从ar1 []移至ar2 []
//将ar2 []中的8插入ar1 []中
第三次迭代后:
ar1 [] = {1、3、5、8、9、10};
AR2 [] = {2,13,15,20};
// 13从ar1 []移至ar2 []
//将ar2 []中的3插入ar1 []中
第四次迭代后:
ar1 [] = {1,2,3,5,8,9};
ar2 [] = {10,13,15,20};
// 10从ar1 []移至ar2 []
//将ar2 []中的2插入ar1 []中
-!>
方法2:
可以通过观察在并行遍历两个排序的数组时进一步优化该解决方案,如果遇到第j个第二数组元素小于第i个第一个数组元素,则将包含第j个元素并替换第一个数组中的第k个元素。该观察结果有助于我们采用以下算法
算法
1) Initialize i,j,k as 0,0,n-1 where n is size of arr1
2) Iterate through every element of arr1 and arr2 using two pointers i and j respectively
if arr1[i] is less than arr2[j]
increment i
else
swap the arr2[j] and arr1[k]
increment j and decrement k
3) Sort both arr1 and arr2
下面是上述算法的实现
C++
// CPP program for the above approach
#include
using namespace std;
// Function to merge two arrays
void merge(int arr1[], int arr2[], int n, int m)
{
int i = 0, j = 0, k = n - 1;
// Untill i less than equal to k
// or j is less tha m
while (i <= k and j < m) {
if (arr1[i] < arr2[j])
i++;
else {
swap(arr2[j++], arr1[k--]);
}
}
// Sort first array
sort(arr1, arr1 + n);
// Sort second array
sort(arr2, arr2 + m);
}
// Driver Code
int main()
{
int ar1[] = { 1, 5, 9, 10, 15, 20 };
int ar2[] = { 2, 3, 8, 13 };
int m = sizeof(ar1) / sizeof(ar1[0]);
int n = sizeof(ar2) / sizeof(ar2[0]);
merge(ar1, ar2, m, n);
cout << "After Merging \nFirst Array: ";
for (int i = 0; i < m; i++)
cout << ar1[i] << " ";
cout << "\nSecond Array: ";
for (int i = 0; i < n; i++)
cout << ar2[i] << " ";
return 0;
}
Java
// Java program for the above approach
import java.util.Arrays;
import java.util.Collections;
class GFG {
static int arr1[] = new int[] { 1, 5, 9, 10, 15, 20 };
static int arr2[] = new int[] { 2, 3, 8, 13 };
// Function to merge two arrays
static void merge(int m, int n)
{
int i = 0, j = 0, k = n - 1;
while (i <= k and j < m) {
if (arr1[i] < arr2[j])
i++;
else {
int temp = arr2[j];
arr2[j] = arr1[k];
arr1[k] = temp;
j++;
k--;
}
}
Arrays.sort(arr1);
Arrays.sort(arr2);
}
public static void main(String[] args)
{
merge(arr1.length, arr2.length);
System.out.print("After Merging \nFirst Array: ");
System.out.println(Arrays.toString(arr1));
System.out.print("Second Array: ");
System.out.println(Arrays.toString(arr2));
}
}
输出
After Merging
First Array: 1 2 3 5 8 9
Second Array: 10 13 15 20
复杂性:
时间复杂度:在最坏的情况下,在while循环中遍历数组时的时间复杂度为O(n + m),而排序为O(nlog(n)+ mlog(m))。因此,代码的总体时间复杂度变为O((n + m)log(n + m))。
空间复杂度:由于函数不对任何操作使用任何额外的数组,因此空间复杂度为O(1)。