给定顺序
查找在字典上最小的(按字典顺序排列)最小的排列
S的排列与S的任何排列一样,使得S中没有两个元素及其排列出现在同一位置。
例子:
Input: 3
Output : 2 3 1
Explanation: The Sequence is 1 2 3.
Possible permutations are (1, 2, 3), (1, 3, 2),
(2, 1, 3), (2, 3, 1), (3, 1, 2) (3, 2, 1).
Derangements are (2, 3, 1), (3, 1, 2).
Smallest Derangement: (2, 3, 1)
Input : 5
Output : 2 1 4 5 3.
Explanation: Out of all the permutations of
(1, 2, 3, 4, 5), (2, 1, 4, 5, 3) is the first derangement.
方法1:
我们可以修改本文中显示的方法:最大排列
使用最小堆,我们可以连续获取最少的元素并将其放置在更重要的位置,同时注意保持排列的属性。
复杂度: O(N * log N)
下面是上述方法的实现。
C++
// C++ program to generate smallest derangement
// using priority queue.
#include
using namespace std;
void generate_derangement(int N)
{
// Generate Sequence and insert into a
// priority queue.
int S[N + 1];
priority_queue, greater > PQ;
for (int i = 1; i <= N; i++) {
S[i] = i;
PQ.push(S[i]);
}
// Generate Least Derangement
int D[N + 1];
for (int i = 1; i <= N; i++) {
int d = PQ.top();
PQ.pop();
if (d != S[i] || i == N) {
D[i] = d;
}
else {
D[i] = PQ.top();
PQ.pop();
PQ.push(d);
}
}
if (D[N] == S[N])
swap(D[N-1], D[N]);
// Print Derangement
for (int i = 1; i <= N; i++)
printf("%d ", D[i]);
printf("\n");
}
// Driver code
int main()
{
generate_derangement(10);
return 0;
}
Java
// Java program to generate
// smallest derangement
// using priority queue.
import java.util.*;
class GFG{
static void generate_derangement(int N)
{
// Generate Sequence and insert
// into a priority queue.
int []S = new int[N + 1];
PriorityQueue PQ =
new PriorityQueue <>();
for (int i = 1; i <= N; i++)
{
S[i] = i;
PQ.add(S[i]);
}
// Generate Least Derangement
int []D = new int[N + 1];
for (int i = 1; i <= N; i++)
{
int d = PQ.peek();
PQ.remove();
if (d != S[i] || i == N)
{
D[i] = d;
}
else
{
D[i] = PQ.peek();
PQ.remove();
PQ.add(d);
}
}
if (D[N] == S[N])
{
int t = D[N - 1];
D[N - 1] = D[N];
D[N] = t;
}
// Print Derangement
for (int i = 1; i <= N; i++)
System.out.printf("%d ", D[i]);
System.out.printf("\n");
}
// Driver code
public static void main(String[] args)
{
generate_derangement(10);
}
}
// This code is contributed by Amit Katiyar
Python3
# Python3 program to generate
# smallest derangement
# using priority queue.
def generate_derangement(N) :
# Generate Sequence and insert
# into a priority queue.
S = [i for i in range(N + 1)]
PQ = []
for i in range(1, N + 1) :
PQ.append(S[i])
# Generate Least Derangement
D = [0] * (N + 1)
PQ.sort()
for i in range(1, N + 1) :
PQ.sort()
d = PQ[0]
del PQ[0]
if (d != S[i]) or (i == N) :
D[i] = d
else :
PQ.sort()
D[i] = PQ[0]
del PQ[0]
PQ.append(d)
if D[N] == S[N] :
t = D[N - 1]
D[N - 1] = D[N]
D[N] = t
# Print Derangement
for i in range(1, N + 1) :
print(D[i], end = " ")
print()
generate_derangement(10)
# This code is contributed by divyeshrabadiya07
C#
// C# program to generate
// smallest derangement
// using priority queue.
using System;
using System.Collections.Generic;
class GFG{
static void generate_derangement(int N)
{
// Generate Sequence and insert
// into a priority queue.
int []S = new int[N + 1];
List PQ = new List ();
for(int i = 1; i <= N; i++)
{
S[i] = i;
PQ.Add(S[i]);
}
// Generate Least Derangement
int []D = new int[N + 1];
PQ.Sort();
for(int i = 1; i <= N; i++)
{
PQ.Sort();
int d = PQ[0];
PQ.RemoveAt(0);
if (d != S[i] || i == N)
{
D[i] = d;
}
else
{
PQ.Sort();
D[i] = PQ[0];
PQ.RemoveAt(0);
PQ.Add(d);
}
}
if (D[N] == S[N])
{
int t = D[N - 1];
D[N - 1] = D[N];
D[N] = t;
}
// Print Derangement
for(int i = 1; i <= N; i++)
Console.Write(D[i] + " ");
Console.Write("\n");
}
// Driver code
public static void Main(String[] args)
{
generate_derangement(10);
}
}
// This code is contributed by Amit Katiyar
C++
// Efficient C++ program to find smallest
// derangement.
#include
void generate_derangement(int N)
{
// Generate Sequence S
int S[N + 1];
for (int i = 1; i <= N; i++)
S[i] = i;
// Generate Derangement
int D[N + 1];
for (int i = 1; i <= N; i += 2) {
if (i == N && i%N!=0) {
// Only if i is odd
// Swap D[N-1] and D[N]
int temp=D[N]
D[N] = D[N - 1];
D[N - 1] = temp;
}
else {
D[i] = i + 1;
D[i + 1] = i;
}
}
// Print Derangement
for (int i = 1; i <= N; i++)
printf("%d ", D[i]);
printf("\n");
}
// Driver Program
int main()
{
generate_derangement(10);
return 0;
}
Java
// Efficient Java program to find
// smallest derangement.
class GFG
{
static void generate_derangement(int N)
{
// Generate Sequence S
int S[] = new int[N + 1];
for (int i = 1; i <= N; i++)
S[i] = i;
// Generate Derangement
int D[] = new int[N + 1];
for (int i = 1; i <= N; i += 2)
{
if (i == N)
{
// Only if i is odd
// Swap S[N-1] and S[N]
D[N] = S[N - 1];
D[N - 1] = S[N];
}
else
{
D[i] = i + 1;
D[i + 1] = i;
}
}
// Print Derangement
for (int i = 1; i <= N; i++)
System.out.print(D[i] + " ");
System.out.println();
}
// Driver Program
public static void main(String[] args)
{
generate_derangement(10);
}
}
// This code is contributed by Arnab Kundu
Python3
# Efficient Python3 program to find
# smallest derangement.
def generate_derangement(N):
# Generate Sequence S
S = [0] * (N + 1)
for i in range(1, N + 1):
S[i] = i
# Generate Derangement
D = [0] * (N + 1)
for i in range(1, N + 1, 2):
if i == N:
# Only if i is odd
# Swap S[N-1] and S[N]
D[N] = S[N - 1]
D[N - 1] = S[N]
else:
D[i] = i + 1
D[i + 1] = i
# Print Derangement
for i in range(1, N + 1):
print(D[i], end = " ")
print()
# Driver Code
if __name__ == '__main__':
generate_derangement(10)
# This code is contributed by PranchalK
C#
// Efficient C# program to find
// smallest derangement.
using System;
class GFG
{
static void generate_derangement(int N)
{
// Generate Sequence S
int[] S = new int[N + 1];
for (int i = 1; i <= N; i++)
S[i] = i;
// Generate Derangement
int[] D = new int[N + 1];
for (int i = 1; i <= N; i += 2)
{
if (i == N)
{
// Only if i is odd
// Swap S[N-1] and S[N]
D[N] = S[N - 1];
D[N - 1] = S[N];
}
else
{
D[i] = i + 1;
D[i + 1] = i;
}
}
// Print Derangement
for (int i = 1; i <= N; i++)
Console.Write(D[i] + " ");
Console.WriteLine();
}
// Driver Program
public static void Main()
{
generate_derangement(10);
}
}
// This code is contributed
// by Akanksha Rai
PHP
Javascript
输出:
2 1 4 3 6 5 8 7 10 9
方法二
由于我们给出了一个非常具体的序列,即
我们可以更有效地计算答案。
将原始序列分为两个元素对,然后交换每个对中的元素。
如果N为奇数,则需要再次交换最后一对。
绘画作品
复杂度:我们最多执行N / 2 + 1交换,因此复杂度为O(N)。
为什么这种方法有效
此方法是方法1的非常特定的应用,并且基于观察。给定序列的性质,在位置i处,我们已经知道可以放置的最小元素,即i + 1或i-1。由于已经给定了S的最小排列,因此很明显,排列必须从2开始而不是从1开始,即形式为i + 1(i = 1)。下一个元素的格式为i – 1。之后的元素将是i + 1,然后是下一个i –1。此模式将一直持续到结束。
此操作最容易理解为S元素对中相邻元素的交换。
如果我们可以在恒定时间内确定最少的元素,那么就可以消除堆的复杂性开销。因此,复杂度从O(N * log N)降低为O(N)。
下面是上述方法的实现:
C++
// Efficient C++ program to find smallest
// derangement.
#include
void generate_derangement(int N)
{
// Generate Sequence S
int S[N + 1];
for (int i = 1; i <= N; i++)
S[i] = i;
// Generate Derangement
int D[N + 1];
for (int i = 1; i <= N; i += 2) {
if (i == N && i%N!=0) {
// Only if i is odd
// Swap D[N-1] and D[N]
int temp=D[N]
D[N] = D[N - 1];
D[N - 1] = temp;
}
else {
D[i] = i + 1;
D[i + 1] = i;
}
}
// Print Derangement
for (int i = 1; i <= N; i++)
printf("%d ", D[i]);
printf("\n");
}
// Driver Program
int main()
{
generate_derangement(10);
return 0;
}
Java
// Efficient Java program to find
// smallest derangement.
class GFG
{
static void generate_derangement(int N)
{
// Generate Sequence S
int S[] = new int[N + 1];
for (int i = 1; i <= N; i++)
S[i] = i;
// Generate Derangement
int D[] = new int[N + 1];
for (int i = 1; i <= N; i += 2)
{
if (i == N)
{
// Only if i is odd
// Swap S[N-1] and S[N]
D[N] = S[N - 1];
D[N - 1] = S[N];
}
else
{
D[i] = i + 1;
D[i + 1] = i;
}
}
// Print Derangement
for (int i = 1; i <= N; i++)
System.out.print(D[i] + " ");
System.out.println();
}
// Driver Program
public static void main(String[] args)
{
generate_derangement(10);
}
}
// This code is contributed by Arnab Kundu
Python3
# Efficient Python3 program to find
# smallest derangement.
def generate_derangement(N):
# Generate Sequence S
S = [0] * (N + 1)
for i in range(1, N + 1):
S[i] = i
# Generate Derangement
D = [0] * (N + 1)
for i in range(1, N + 1, 2):
if i == N:
# Only if i is odd
# Swap S[N-1] and S[N]
D[N] = S[N - 1]
D[N - 1] = S[N]
else:
D[i] = i + 1
D[i + 1] = i
# Print Derangement
for i in range(1, N + 1):
print(D[i], end = " ")
print()
# Driver Code
if __name__ == '__main__':
generate_derangement(10)
# This code is contributed by PranchalK
C#
// Efficient C# program to find
// smallest derangement.
using System;
class GFG
{
static void generate_derangement(int N)
{
// Generate Sequence S
int[] S = new int[N + 1];
for (int i = 1; i <= N; i++)
S[i] = i;
// Generate Derangement
int[] D = new int[N + 1];
for (int i = 1; i <= N; i += 2)
{
if (i == N)
{
// Only if i is odd
// Swap S[N-1] and S[N]
D[N] = S[N - 1];
D[N - 1] = S[N];
}
else
{
D[i] = i + 1;
D[i + 1] = i;
}
}
// Print Derangement
for (int i = 1; i <= N; i++)
Console.Write(D[i] + " ");
Console.WriteLine();
}
// Driver Program
public static void Main()
{
generate_derangement(10);
}
}
// This code is contributed
// by Akanksha Rai
的PHP
Java脚本
输出:
2 1 4 3 6 5 8 7 10 9
注意:如果我们对S本身执行交换操作,则辅助空间可以减小为O(1)。