围绕给定范围对数组进行三向分区
给定一个数组和一个范围 [ lowVal , highVal ],围绕范围划分数组,使数组分为三部分。
1) 所有小于lowVal的元素都排在第一位。
2) 接下来是lowVal到highVVal范围内的所有元素。
3)所有大于highVVal的元素都出现在最后。
三组的各个元素可以以任何顺序出现。
例子:
Input: arr[] = {1, 14, 5, 20, 4, 2, 54, 20, 87, 98, 3, 1, 32}
lowVal = 14, highVal = 20
Output: arr[] = {1, 5, 4, 2, 1, 3, 14, 20, 20, 98, 87, 32, 54}
Input: arr[] = {1, 14, 5, 20, 4, 2, 54, 20, 87, 98, 3, 1, 32}
lowVal = 20, highVal = 20
Output: arr[] = {1, 14, 5, 4, 2, 1, 3, 20, 20, 98, 87, 32, 54}
一个简单的解决方案是对数组进行排序。这个解决方案做了很多额外的重新排列,需要 O(n Log n) 时间。
一种有效的解决方案是基于基于荷兰国旗的 QuickSort。我们从左边遍历给定的数组元素。我们跟踪两个指针,第一个(在下面的代码中称为 start)从开始存储较小元素(小于范围)的下一个位置;第二个(在下面的代码中称为 end)存储从末尾开始的更大元素的下一个位置。
C++
// C++ program to implement three way partitioning
// around a given range.
#include
using namespace std;
// Partitions arr[0..n-1] around [lowVal..highVal]
void threeWayPartition(int arr[], int n,
int lowVal, int highVal)
{
// Initialize ext available positions for
// smaller (than range) and greater elements
int start = 0, end = n-1;
// Traverse elements from left
for (int i=0; i<=end;)
{
// If current element is smaller than
// range, put it on next available smaller
// position.
if (arr[i] < lowVal)
{
//if i and start are same in that case we can't swap
//swap only if i is greater than start
if(i==start)
{
start++;
i++;
}
else
swap(arr[i++], arr[start++]);
}
// If current element is greater than
// range, put it on next available greater
// position.
else if (arr[i] > highVal)
swap(arr[i], arr[end--]);
else
i++;
}
}
// Driver code
int main()
{
int arr[] = {1, 14, 5, 20, 4, 2, 54, 20, 87,
98, 3, 1, 32};
int n = sizeof(arr)/sizeof(arr[0]);
threeWayPartition(arr, n, 10, 20);
cout << "Modified array \n";
for (int i=0; i
Java
// Java program to implement three way partitioning
// around a given range.
import java.io.*;
class GFG
{
// Partitions arr[0..n-1] around [lowVal..highVal]
public static void threeWayPartition(int[] arr, int lowVal, int highVal)
{
int n = arr.length;
// Initialize ext available positions for
// smaller (than range) and greater elements
int start = 0, end = n-1;
// Traverse elements from left
for(int i = 0; i <= end;)
{
// If current element is smaller than
// range, put it on next available smaller
// position.
if(arr[i] < lowVal)
{
int temp = arr[start];
arr[start] = arr[i];
arr[i] = temp;
start++;
i++;
}
// If current element is greater than
// range, put it on next available greater
// position.
else if(arr[i] > highVal)
{
int temp = arr[end];
arr[end] = arr[i];
arr[i] = temp;
end--;
}
else
i++;
}
}
public static void main (String[] args)
{
int arr[] = {1, 14, 5, 20, 4, 2, 54, 20, 87, 98, 3, 1, 32};
threeWayPartition(arr, 10, 20);
System.out.println("Modified array ");
for (int i=0; i < arr.length; i++)
{
System.out.print(arr[i] + " ");
}
}
}
//This code is contributed by Dheerendra Singh
Python3
# Python3 program to implement three way
# partitioning around a given range.
# Partitions arr[0..n-1] around [lowVal..highVal]
def threeWayPartition(arr, n, lowVal, highVal):
# Initialize ext available positions for
# smaller (than range) and greater elements
start = 0
end = n - 1
i = 0
# Traverse elements from left
while i <= end:
# If current element is smaller than
# range, put it on next available smaller
# position.
if arr[i] < lowVal:
arr[i], arr[start] = arr[start], arr[i]
i += 1
start += 1
# If current element is greater than
# range, put it on next available greater
# position.
elif arr[i] > highVal:
arr[i], arr[end] = arr[end], arr[i]
end -= 1
else:
i += 1
# Driver code
if __name__ == "__main__":
arr = [1, 14, 5, 20, 4, 2, 54,
20, 87, 98, 3, 1, 32]
n = len(arr)
threeWayPartition(arr, n, 10, 20)
print("Modified array")
for i in range(n):
print(arr[i], end = " ")
# This code is contributed by
# sanjeev2552
C#
// C# program to implement three way
// partitioning around a given range.
using System;
class GFG {
// Partitions arr[0..n-1]
// around [lowVal..highVal]
public static void threeWayPartition(int[] arr,
int lowVal, int highVal)
{
int n = arr.Length;
// Initialize ext available positions for
// smaller (than range) and greater elements
int start = 0, end = n - 1;
// Traverse elements from left
for (int i = 0; i <= end;) {
// If current element is smaller than
// range, put it on next available smaller
// position.
if (arr[i] < lowVal) {
int temp = arr[start];
arr[start] = arr[i];
arr[i] = temp;
start++;
i++;
}
// If current element is greater than
// range, put it on next available greater
// position.
else if (arr[i] > highVal) {
int temp = arr[end];
arr[end] = arr[i];
arr[i] = temp;
end--;
}
else
i++;
}
}
// Driver code
public static void Main()
{
int[] arr = { 1, 14, 5, 20, 4, 2, 54,
20, 87, 98, 3, 1, 32 };
threeWayPartition(arr, 10, 20);
Console.WriteLine("Modified array ");
for (int i = 0; i < arr.Length; i++) {
Console.Write(arr[i] + " ");
}
}
}
// This article is contributed by vt_m.
Javascript
输出:
Modified array
1 5 4 2 1 3 14 20 20 98 87 32 54
时间复杂度: O(n)
辅助空间: O(1)