使用二分搜索算法重新排列数组以找到 K,无需排序
给定一个包含N个不同整数的数组arr[]和一个整数K ,任务是以这样一种方式重新排列给定的数组,使得可以借助二分搜索算法在重新排列的数组中找到K。请注意,该数组不进行排序。
例子:
Input: arr[] = {10, 7, 2, 5, 3, 8}, K = 7
Output: 3 7 8 5 2 10
Explanation: Finding K in output array {3, 7, 8, 5, 2, 10} using Binary Search
— initially, left (L) = 0, right (R) = 5, mid = 2, i.e. 8 (not equal to K)
— since 8 > K, therefore left (L) = 0, right (R) = 1, mid = 0, i.e. 3(not equal to K)
— since 3 < K, therefore left (L) = 1, right (R) = 1, mid = 1, i.e. 7 (which is equal to K)
Hence K can be found in output array using Binary Search, even the array is unsorted.
Input: arr[] = {10, 7, 2, 5, 8, 6}, K = 6
Output: 8 7 5 10 2 6
方法:可以根据以下观察解决给定的问题:
- An integer K can be found in a sorted array arr[] using the binary search algorithm as follows:
- Initially, L = 0 and R = N-1.
- While L is less than or equal to R:
- Find the mid point of the current range [L, R] as mid = (L+R)/2.
- If arr[mid] is equal to K, it returns true.
- Else, if arr[mid] is greater than K, then update R to mid-1 i.e, all elements right of mid are skipped.
- Else, if arr[mid] is less than K, then update L to mid+1 i.e, all elements left of mid are skipped.
- If K is not found, then return false.
- The binary search algorithm may fail on unsorted arrays because the array doesn’t meet the criteria of the array being monotonically increasing or decreasing. But, sometimes the binary search algorithm may also work on unsorted arrays.
- For example, suppose the given array, arr[] is equal to {2, 1, 5, 4, 3} and K is equal to 2. Then the algorithm works as:
- In the first iteration:
- The L=0 and R= 4, therefore mid = (4+0)/2 =2.
- The arr[2] (=5) is greater than 2, so assign mid-1 to R. Now R becomes 1.
- In the second Iteration:
- The L=0 and R= 1, therefore mid = (1+0)/2 =0.
- The arr[0] (=2) is equal to 2. Therefore, return true.
- In the first iteration:
- Therefore, from above, it can be observed that, to go the index X, from a position mid, there are two cases:
- If mid is less than X, then arr[mid] has to be less than arr[X], to move towards index X, which lies on the right side of mid.
- Else, if mid is greater than X then arr[mid] has to be greater than arr[X], to move towards index X, which lies on the left side of mid
请按照以下步骤解决问题:
- 初始化一个数组,比如ans[] ,所有数组元素都为-1以存储重新排列的数组。
- 此外,初始化两个向量,表示小于和大于K 以存储小于和大于K的元素。
- 遍历数组arr[]并在当前元素小于K时将其推入较小的值。否则,如果它大于K ,则将其推入更大。
- 在数组arr[]中找到元素K的索引,然后将其值分配给K 。
- 初始化两个变量,比如低为0和高为N-1 ,以执行二分搜索。
- 迭代直到low小于或等于high并执行以下步骤:
- 找到当前范围的中间值[low, high]并将其存储在一个变量中,比如mid 。
- 如果mid小于K ,则执行以下操作:
- 如果small.size()为0 ,则打印“ -1 ”并返回。
- 否则,将向量的最后一个元素更小分配给ans[mid] ,然后弹出更小的最后一个元素。
- 如果mid大于K ,则执行以下操作:
- 如果greater.size()为0 ,则打印“ -1 ”并返回。
- 否则,将向量的最后一个元素更大,分配给ans[mid] ,然后弹出更大的最后一个元素。
- 如果mid等于K ,则将arr[K]分配给ans[mid]然后中断。
- 完成上述步骤后,遍历数组ans[] ,如果当前元素为“ -1 ”即未填充,则为其分配任何未使用的元素。
- 最后,将数组ans[]打印为重新排列的数组。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to rearrange the array
void Rearrange(int arr[], int K, int N)
{
// Stores the rearranged array
int ans[N + 1];
// Stores whether the arrangement
// is possible or not
int f = -1;
for (int i = 0; i < N; i++) {
ans[i] = -1;
}
// Update K with the position of K
K = find(arr, arr + N, K) - arr;
// Stores all elements lesser than
// and greater than in vector smaller
// and greater respectively
vector smaller, greater;
// Traverse the array arr[]
for (int i = 0; i < N; i++) {
// If arr[i] is less than arr[K]
if (arr[i] < arr[K])
smaller.push_back(arr[i]);
// Else
else if (arr[i] > arr[K])
greater.push_back(arr[i]);
}
int low = 0, high = N - 1;
// Iterate until low is less than or
// equal to high
while (low <= high) {
// Stores mid point
int mid = (low + high) / 2;
// If mid is equal to K
if (mid == K) {
ans[mid] = arr[K];
f = 1;
break;
}
// If mid is less than K
else if (mid < K) {
if (smaller.size() == 0) {
break;
}
ans[mid] = smaller.back();
smaller.pop_back();
low = mid + 1;
}
// If mid is greater than K
else {
if (greater.size() == 0) {
break;
}
ans[mid] = greater.back();
greater.pop_back();
high = mid - 1;
}
}
// If f is -1
if (f == -1) {
cout << -1 << endl;
return;
}
// Iterate in the range [1, N]
for (int i = 0; i < N; i++) {
// If ans[i] is equal to -1
if (ans[i] == -1) {
if (smaller.size()) {
ans[i] = smaller.back();
smaller.pop_back();
}
else if (greater.size()) {
ans[i] = greater.back();
greater.pop_back();
}
}
}
// Print the rearranged array
for (int i = 0; i < N; i++)
cout << ans[i] << " ";
cout << endl;
}
// Driver Code
int main()
{
// Input
int arr[] = { 10, 7, 2, 5, 3, 8 };
int K = 7;
int N = sizeof(arr) / sizeof(arr[0]);
// Function Call
Rearrange(arr, K, N);
return 0;
}
Java
// Java program for the above approach
import java.util.*;
public class GFG
{
// Function to rearrange the array
static void Rearrange(int arr[], int K, int N)
{
// Stores the rearranged array
int ans[] = new int[N + 1];
// Stores whether the arrangement
// is possible or not
int f = -1;
for (int i = 0; i < N; i++) {
ans[i] = -1;
}
// Update K with the position of K
for (int i = 0; i < arr.length; i++)
{
if (arr[i] == K)
{
K = i;
break;
}
}
// Stores all elements lesser than
// and greater than in vector smaller
// and greater respectively
Vector smaller = new Vector();
Vector greater = new Vector();
// Traverse the array arr[]
for (int i = 0; i < N; i++) {
// If arr[i] is less than arr[K]
if (arr[i] < arr[K])
smaller.add(arr[i]);
// Else
else if (arr[i] > arr[K])
greater.add(arr[i]);
}
int low = 0, high = N - 1;
// Iterate until low is less than or
// equal to high
while (low <= high) {
// Stores mid point
int mid = (low + high) / 2;
// If mid is equal to K
if (mid == K) {
ans[mid] = arr[K];
f = 1;
break;
}
// If mid is less than K
else if (mid < K) {
if (smaller.size() == 0) {
break;
}
ans[mid] = smaller.lastElement();
smaller.remove(smaller.size()-1);
low = mid + 1;
}
// If mid is greater than K
else {
if (greater.size() == 0) {
break;
}
ans[mid] = greater.lastElement();
greater.remove(greater.size()-1);
high = mid - 1;
}
}
// If f is -1
if (f == -1) {
System.out.println(-1 );
return;
}
// Iterate in the range [1, N]
for (int i = 0; i < N; i++) {
// If ans[i] is equal to -1
if (ans[i] == -1) {
if (smaller.size()>0) {
ans[i] = smaller.lastElement();
smaller.remove(smaller.size()-1);
}
else if (greater.size()>0) {
ans[i] = greater.lastElement();
greater.remove(greater.size()-1);
}
}
}
// Print the rearranged array
for (int i = 0; i < N; i++)
System.out.print(ans[i] +" ");
System.out.println();
}
// Driver code
public static void main(String args[])
{
// Input
int arr[] = { 10, 7, 2, 5, 3, 8 };
int K = 7;
int N = arr.length;
// Function Call
Rearrange(arr, K, N);
}
}
// This code is contributed by SoumikMondal
Python3
# Python 3 program for the above approach
# Function to rearrange the array
def Rearrange(arr, K, N):
# Stores the rearranged array
ans = [0]*(N + 1)
# Stores whether the arrangement
# is possible or not
f = -1
for i in range(N):
ans[i] = -1
# Update K with the position of K
K = arr.index(K)
# Stores all elements lesser than
# and greater than in vector smaller
# and greater respectively
smaller = []
greater = []
# Traverse the array arr[]
for i in range(N):
# If arr[i] is less than arr[K]
if (arr[i] < arr[K]):
smaller.append(arr[i])
# Else
elif (arr[i] > arr[K]):
greater.append(arr[i])
low = 0
high = N - 1
# Iterate until low is less than or
# equal to high
while (low <= high):
# Stores mid point
mid = (low + high) // 2
# If mid is equal to K
if (mid == K):
ans[mid] = arr[K]
f = 1
break
# If mid is less than K
elif (mid < K):
if (len(smaller) == 0):
break
ans[mid] = smaller[-1]
smaller.pop()
low = mid + 1
# If mid is greater than K
else:
if (len(greater) == 0):
break
ans[mid] = greater[-1]
greater.pop()
high = mid - 1
# If f is -1
if (f == -1):
print(-1)
return
# Iterate in the range [1, N]
for i in range(N):
# If ans[i] is equal to -1
if (ans[i] == -1):
if (len(smaller)):
ans[i] = smaller[-1]
smaller.pop()
elif (len(greater)):
ans[i] = greater[-1]
greater.pop()
# Print the rearranged array
for i in range(N):
print(ans[i], end=" ")
print()
# Driver Code
if __name__ == "__main__":
# Input
arr = [10, 7, 2, 5, 3, 8]
K = 7
N = len(arr)
# Function Call
Rearrange(arr, K, N)
# This code is contributed by ukasp.
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
public class GFG
{
// Function to rearrange the array
static void Rearrange(int []arr, int K, int N)
{
// Stores the rearranged array
int []ans = new int[N + 1];
// Stores whether the arrangement
// is possible or not
int f = -1;
for (int i = 0; i < N; i++) {
ans[i] = -1;
}
// Update K with the position of K
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] == K)
{
K = i;
break;
}
}
// Stores all elements lesser than
// and greater than in vector smaller
// and greater respectively
List smaller = new List();
List greater = new List();
// Traverse the array []arr
for (int i = 0; i < N; i++) {
// If arr[i] is less than arr[K]
if (arr[i] < arr[K])
smaller.Add(arr[i]);
// Else
else if (arr[i] > arr[K])
greater.Add(arr[i]);
}
int low = 0, high = N - 1;
// Iterate until low is less than or
// equal to high
while (low <= high) {
// Stores mid point
int mid = (low + high) / 2;
// If mid is equal to K
if (mid == K) {
ans[mid] = arr[K];
f = 1;
break;
}
// If mid is less than K
else if (mid < K) {
if (smaller.Count == 0) {
break;
}
ans[mid] = smaller[smaller.Count-1];
smaller.RemoveAt(smaller.Count-1);
low = mid + 1;
}
// If mid is greater than K
else {
if (greater.Count == 0) {
break;
}
ans[mid] = greater[greater.Count-1];
greater.RemoveAt(greater.Count-1);
high = mid - 1;
}
}
// If f is -1
if (f == -1) {
Console.WriteLine(-1 );
return;
}
// Iterate in the range [1, N]
for (int i = 0; i < N; i++) {
// If ans[i] is equal to -1
if (ans[i] == -1) {
if (smaller.Count>0) {
ans[i] = smaller[smaller.Count-1];
smaller.RemoveAt(smaller.Count-1);
}
else if (greater.Count>0) {
ans[i] = greater[greater.Count-1];
greater.RemoveAt(greater.Count-1);
}
}
}
// Print the rearranged array
for (int i = 0; i < N; i++)
Console.Write(ans[i] +" ");
Console.WriteLine();
}
// Driver code
public static void Main(String []args)
{
// Input
int []arr = { 10, 7, 2, 5, 3, 8 };
int K = 7;
int N = arr.Length;
// Function Call
Rearrange(arr, K, N);
}
}
// This code is contributed by Princi Singh
Javascript
3 7 8 5 2 10
时间复杂度: O(N)
辅助空间: O(N)