通过交换满足给定条件的对对前 N 个自然数的排列进行排序
给定一个大小为N的数组p[]表示前N个自然数的排列,其中N是偶数,任务是通过获取一对索引a、b并交换p[a]和p[ b]在每个操作中,其中2 * |a – b| ≥N 。打印在每个操作中交换的索引对。
例子:
Input: p[] = {2, 5, 3, 1, 4, 6}
Output: 3
1 5
2 5
1 4
Explanation:
Operation 1: Swap p[1] and p[5]. Therefore, p[] modifies to {4, 5, 3, 1, 2, 6}.
Operation 2: Swap p[2] and p[5]. Therefore, p[] modifies to {4, 2, 3, 1, 5, 6}.
Operation 3: Swap p[1] and p[4]. Therefore, p[] modifies to {1, 2, 3, 4, 5, 6}.
Therefore, the array is sorted.
Input: p[] = {1, 2, 3, 4}
Output: 0
解决方法:按照以下步骤解决问题:
- 创建一个数组posOfCurrNum[]来存储p[]中存在的数字的位置。
- 使用变量i在[1, N]范围内迭代并将posOfCurrNum[p[i]]设置为i 。
- 声明一个对ans的向量来存储为对给定数组p[]进行排序而执行的交换。
- 使用变量i在[1, N]范围内迭代
- 如果p[i]等于i ,那么这意味着当前数字i已经出现在正确的位置。所以,继续下一次迭代。
- 使用posOfCurrNum[i]初始化变量j以存储数字i的当前位置。
- 现在,出现了4种情况:
- 情况 1:如果|i – j| * 2大于n ,然后,交换(i,j)并将这对存储在ans中。
- 情况 2:如果n/2小于或等于i – 1 ,则swap(i, 1) → swap(1, j) → swap(i, 1)并将这些对存储在ans中。
- 情况 3:如果n/2小于或等于n – j ,则swap(i, n) → swap(j, n) → swap(i, n)并将这些对存储在ans中。
- 情况 4:如果n/2小于j -1并且n/2小于或等于n – i ,则swap(i, n) → swap(n, 1) → swap(1, j) → swap (1, n) → swap(i, n)并将这些对存储在ans中。
- 打印向量的大小ans 。
- 遍历对向量ans并打印每一对。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to swap integers
// in an operation
void Swap(int x, int y, int p[],
int posOfCurrNum[])
{
swap(posOfCurrNum[p[x]],
posOfCurrNum[p[y]]);
swap(p[x], p[y]);
}
// Function to sort permutation
// using given operations
void sortArray(int p[], int n)
{
// Store the position of the
// array elements
int posOfCurrNum[n + 1];
for (int i = 1; i <= n; i++) {
posOfCurrNum[p[i]] = i;
}
// Store the result
vector > ans;
// Traverse the given array, p[]
for (int i = 1; i <= n; i++) {
// If current number is already
// present at the right position
if (p[i] == i) {
continue;
}
// Store the current position of
// the number 'i'
int j = posOfCurrNum[i];
// Case 1: If both the indices
// satisfies the given condition
if (abs(i - j) * 2 >= n) {
Swap(i, j, p, posOfCurrNum);
ans.push_back({ i, j });
}
// Case 2: If the current number
// 'i' is present at right side
// of half of the given array
else if (n / 2 <= i - 1) {
Swap(1, i, p, posOfCurrNum);
ans.push_back({ i, 1 });
Swap(1, j, p, posOfCurrNum);
ans.push_back({ 1, j });
Swap(i, 1, p, posOfCurrNum);
ans.push_back({ i, 1 });
}
// Case 3: If the position of the
// current number 'i' is left side
// of half of the given array
else if (n - j >= n / 2) {
Swap(i, n, p, posOfCurrNum);
ans.push_back({ i, n });
Swap(j, n, p, posOfCurrNum);
ans.push_back({ j, n });
Swap(i, n, p, posOfCurrNum);
ans.push_back({ i, n });
}
// Case 4: For all other cases
else {
Swap(i, n, p, posOfCurrNum);
ans.push_back({ i, n });
Swap(n, 1, p, posOfCurrNum);
ans.push_back({ n, 1 });
Swap(1, j, p, posOfCurrNum);
ans.push_back({ 1, j });
Swap(1, n, p, posOfCurrNum);
ans.push_back({ 1, n });
Swap(i, n, p, posOfCurrNum);
ans.push_back({ i, n });
}
}
// Print the number of operations
cout << ans.size() << '\n';
// Print the steps
for (auto p : ans)
cout << p.first << " "
<< p.second << '\n';
}
// Driver Code
int main()
{
// Given Input
int n = 6;
// Append 0 to consider
// 1-based indexing
int p[] = { 0, 2, 5, 3, 1, 4, 6 };
// Function Call
sortArray(p, n);
return 0;
}
Java
// Java program for the above approach
import java.lang.*;
import java.util.*;
class pair
{
int first, second;
pair(int first, int second)
{
this.first = first;
this.second = second;
}
}
class GFG
{
// Function to swap integers
// in an operation
static void Swap(int x, int y, int p[],
int posOfCurrNum[])
{
int t1 = posOfCurrNum[p[x]];
posOfCurrNum[p[x]] = posOfCurrNum[p[y]];
posOfCurrNum[p[y]] = t1;
int t2 = p[x];
p[x] = p[y];
p[y] = t2;
}
// Function to sort permutation
// using given operations
static void sortArray(int p[], int n)
{
// Store the position of the
// array elements
int[] posOfCurrNum = new int[n + 1];
for (int i = 1; i <= n; i++) {
posOfCurrNum[p[i]] = i;
}
// Store the result
ArrayList ans=new ArrayList<>();
// Traverse the given array, p[]
for (int i = 1; i <= n; i++) {
// If current number is already
// present at the right position
if (p[i] == i) {
continue;
}
// Store the current position of
// the number 'i'
int j = posOfCurrNum[i];
// Case 1: If both the indices
// satisfies the given condition
if (Math.abs(i - j) * 2 >= n) {
Swap(i, j, p, posOfCurrNum);
ans.add(new pair( i, j ));
}
// Case 2: If the current number
// 'i' is present at right side
// of half of the given array
else if (n / 2 <= i - 1) {
Swap(1, i, p, posOfCurrNum);
ans.add(new pair( i, 1 ));
Swap(1, j, p, posOfCurrNum);
ans.add(new pair( 1, j ));
Swap(i, 1, p, posOfCurrNum);
ans.add(new pair( i, 1 ));
}
// Case 3: If the position of the
// current number 'i' is left side
// of half of the given array
else if (n - j >= n / 2) {
Swap(i, n, p, posOfCurrNum);
ans.add(new pair( i, n ));
Swap(j, n, p, posOfCurrNum);
ans.add(new pair( j, n ));
Swap(i, n, p, posOfCurrNum);
ans.add(new pair( i, n ));
}
// Case 4: For all other cases
else {
Swap(i, n, p, posOfCurrNum);
ans.add(new pair( i, n ));
Swap(n, 1, p, posOfCurrNum);
ans.add(new pair( n, 1 ));
Swap(1, j, p, posOfCurrNum);
ans.add(new pair( 1, j ));
Swap(1, n, p, posOfCurrNum);
ans.add(new pair( 1, n ));
Swap(i, n, p, posOfCurrNum);
ans.add(new pair( i, n ));
}
}
// Print the number of operations
System.out.println(ans.size());
// Print the steps
for (pair pp : ans)
System.out.println(pp.first+" "+pp.second);
}
// Driver code
public static void main(String[] args)
{
// Given Input
int n = 6;
// Append 0 to consider
// 1-based indexing
int p[] = { 0, 2, 5, 3, 1, 4, 6 };
// Function Call
sortArray(p, n);
}
}
// This code is contributed by offbeat
Python3
# Python3 program for the above approach
# Function to swap integers
# in an operation
def Swap(x, y, p, posOfCurrNum):
posOfCurrNum[p[x]], posOfCurrNum[p[y]] = posOfCurrNum[p[y]], posOfCurrNum[p[x]]
p[x], p[y] = p[y], p[x]
return p, posOfCurrNum
# Function to sort permutation
# using given operations
def sortArray(p, n):
# Store the position of the
# array elements
posOfCurrNum = [0] * (n + 1)
for i in range(1, n + 1):
posOfCurrNum[p[i]] = i
# Store the result
ans = []
# Traverse the given array, p[]
for i in range(1, n + 1):
# If current number is already
# present at the right position
if (p[i] == i):
continue
# Store the current position of
# the number 'i'
j = posOfCurrNum[i]
# Case 1: If both the indices
# satisfies the given condition
if (abs(i - j) * 2 >= n):
p, posOfCurrNum = Swap(i, j, p, posOfCurrNum)
ans.append([i, j])
# Case 2: If the current number
# 'i' is present at right side
# of half of the given array
elif (n // 2 <= i - 1):
p, posOfCurrNum = Swap(1, i, p, posOfCurrNum)
ans.append([i, 1])
p, posOfCurrNum = Swap(1, j, p, posOfCurrNum)
ans.append([1, j])
p, posOfCurrNum = Swap(i, 1, p, posOfCurrNum)
ans.append([i, 1])
# Case 3: If the position of the
# current number 'i' is left side
# of half of the given array
elif (n - j >= n // 2):
p, posOfCurrNum = Swap(i, n, p, posOfCurrNum)
ans.append([i, n])
p, posOfCurrNum = Swap(j, n, p, posOfCurrNum)
ans.append([j, n])
p, posOfCurrNum = Swap(i, n, p, posOfCurrNum)
ans.append([i, n])
# Case 4: For all other cases
else:
p, posOfCurrNum = Swap(i, n, p, posOfCurrNum)
ans.append([i, n])
p, posOfCurrNum = Swap(n, 1, p, posOfCurrNum)
ans.append([n, 1])
p, posOfCurrNum = Swap(1, j, p, posOfCurrNum)
ans.append([1, j])
p, posOfCurrNum = Swap(1, n, p, posOfCurrNum)
ans.append([1, n])
p, posOfCurrNum = Swap(i, n, p, posOfCurrNum)
ans.append([i, n])
# Print the number of operations
print(len(ans))
# Print the steps
for p in ans:
print(p[0], p[1])
# Driver Code
if __name__ == '__main__':
# Given Input
n = 6
# Append 0 to consider
# 1-based indexing
p = [ 0, 2, 5, 3, 1, 4, 6 ]
# Function Call
sortArray(p, n)
# This code is contributed by mohit kumar 29
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
class GFG {
// Function to swap integers
// in an operation
static void Swap(int x, int y, int[] p,
int[] posOfCurrNum)
{
int t1 = posOfCurrNum[p[x]];
posOfCurrNum[p[x]] = posOfCurrNum[p[y]];
posOfCurrNum[p[y]] = t1;
int t2 = p[x];
p[x] = p[y];
p[y] = t2;
}
// Function to sort permutation
// using given operations
static void sortArray(int[] p, int n)
{
// Store the position of the
// array elements
int[] posOfCurrNum = new int[n + 1];
for (int i = 1; i <= n; i++) {
posOfCurrNum[p[i]] = i;
}
// Store the result
List> ans = new List>();
// Traverse the given array, p[]
for (int i = 1; i <= n; i++) {
// If current number is already
// present at the right position
if (p[i] == i) {
continue;
}
// Store the current position of
// the number 'i'
int j = posOfCurrNum[i];
// Case 1: If both the indices
// satisfies the given condition
if (Math.Abs(i - j) * 2 >= n) {
Swap(i, j, p, posOfCurrNum);
ans.Add(new Tuple(i, j));
}
// Case 2: If the current number
// 'i' is present at right side
// of half of the given array
else if (n / 2 <= i - 1) {
Swap(1, i, p, posOfCurrNum);
ans.Add(new Tuple(i, 1));
Swap(1, j, p, posOfCurrNum);
ans.Add(new Tuple(1, j));
Swap(i, 1, p, posOfCurrNum);
ans.Add(new Tuple(i, 1));
}
// Case 3: If the position of the
// current number 'i' is left side
// of half of the given array
else if (n - j >= n / 2) {
Swap(i, n, p, posOfCurrNum);
ans.Add(new Tuple(i, n));
Swap(j, n, p, posOfCurrNum);
ans.Add(new Tuple(j, n));
Swap(i, n, p, posOfCurrNum);
ans.Add(new Tuple(i, n));
}
// Case 4: For all other cases
else {
Swap(i, n, p, posOfCurrNum);
ans.Add(new Tuple(i, n));
Swap(n, 1, p, posOfCurrNum);
ans.Add(new Tuple(n, 1));
Swap(1, j, p, posOfCurrNum);
ans.Add(new Tuple(1, 4));
Swap(1, n, p, posOfCurrNum);
ans.Add(new Tuple(1, 6));
Swap(i, n, p, posOfCurrNum);
ans.Add(new Tuple(i, n));
}
}
// Print the number of operations
Console.WriteLine(ans.Count);
// Print the steps
foreach(Tuple pp in ans)
Console.WriteLine(pp.Item1+" "+pp.Item2);
}
// Driver code
static void Main()
{
// Given Input
int n = 6;
// Append 0 to consider
// 1-based indexing
int[] p = { 0, 2, 5, 3, 1, 4, 6 };
// Function Call
sortArray(p, n);
}
}
// This code is contributed by mukesh07.
Javascript
输出:
9
1 4
2 6
6 1
1 4
1 6
2 6
4 1
1 5
4 1
时间复杂度: O(N)
辅助空间: O(N)