给定n个正整数的数组,使得每个整数元素从1到n。找到可以通过替换数组中最小数量的元素而获得的字典排列,以使数组中的每个元素在整个数组中恰好出现一个。首先打印所需的最少数量的替换,然后打印最终的字典排列。
例子:
Input arr[] = {2, 3, 4, 3, 2}
Output 2
1 3 4 5 2
Explanation
Replace number '2' at position 1st with number
'1' and '3' at position 4th with number '5'.
The array that we obtain is [1, 3, 4, 5, 2]
which is lexicographically smallest among all
the possible suitable.
Input arr[] = {2, 1, 2, 1, 2}
Output 3
2 1 3 4 5
天真的方法是生成从1到n的所有置换,并选择最小的置换。这种方法的时间复杂度为O(n!),对于较大的n值,肯定会超时。
高效的方法是贪婪地选择所需的元素。首先初始化cnt []数组,该数组将包含该数组中出现的元素的频率。对于在数组中多次出现的array(a i )的每个元素,由于按字典顺序排列的最小排列,请按升序添加数字。例如,
遍历所有元素的数组。令当前数组个数为i 。如果i的计数等于1,则移至下一个数组数。如果A I计数大于1然后替换仅当ELE I A I与元件ELE(其未在阵列发生最小的数)的数目。同时减少cnt []数组中i的数量。
如果ele> a i,则标记数字a i,以便我们可以在下一次迭代中替换它。之所以需要执行此步骤,是因为我们需要对字典进行最小的排列。
For example, let’s suppose the arr[] = {1, 5, 4, 5, 3, 7, 3}
In first iteration ‘5’ occurs two times in array(indexing 1),
therefore we have to replace ‘5’ at position ‘2’ with ‘2’(2 < 5).
Now the updated array = {1, 2, 4, 5, 3, 7, 3}
In next iteration, ‘3’ would be consider as it occurs two times
in array. But this time the next element of replacement would
be equals to 6 which is greater than 3. Therefore visit element
3 in boolean array vis[] and iterate over other elements.
Now again ‘3’ occurred at position 7th, this time replace it with
number ‘6’.
Final array is arr[] = {1, 2, 4, 5, 3, 7, 6}
C++
// C++ program to print lexicographically
// permutation array by replacing minimum
// element of array
#include
using namespace std;
// Function to calculate lexicographically permutation
// in array
void lexicoSmallestPermuatation(int arr[], int n)
{
// Calculate frequency of array elements
int cnt[n + 1];
memset(cnt, 0, sizeof(cnt));
for (int i = 0; i < n; ++i)
++cnt[arr[i]];
int ele = 1, replacement = 0;
bool vis[n + 1];
memset(vis, 0, sizeof(vis));
for (int i = 0; i < n; ++i) {
// If count of element is 1, no
// need to replace
if (cnt[arr[i]] == 1)
continue;
// Find the element that has not
// occurred in array
while (cnt[ele])
++ele;
// If replacement element is greater
// than current arr[i] then visit
// that element for next iteration
if (ele > arr[i] && !vis[arr[i]])
vis[arr[i]] = 1;
else {
// Decrement count and assign the element
// to array
--cnt[arr[i]];
arr[i] = ele;
// Increment the replacement count
++replacement;
// Increment element after assigning
// to the array
++ele;
}
}
cout << replacement << "\n";
for (int i = 0; i < n; ++i)
cout << arr[i] << " ";
}
// Driver code
int main()
{
int arr[] = { 2, 3, 4, 3, 2 };
int sz = sizeof(arr) / sizeof(arr[0]);
lexicoSmallestPermuatation(arr, sz);
return 0;
}
Java
// Java program to print lexicographically
// permutation array by replacing minimum
// element of array
class GFG {
// Function to calculate lexicographically permutation
// in array
static void lexicoSmallestPermuatation(int arr[], int n) {
// Calculate frequency of array elements
int cnt[] = new int[n + 1];
for (int i = 0; i < n; ++i) {
++cnt[arr[i]];
}
int ele = 1, replacement = 0;
boolean vis[] = new boolean[n + 1];
for (int i = 0; i < n; ++i) {
// If count of element is 1, no
// need to replace
if (cnt[arr[i]] == 1) {
continue;
}
// Find the element that has not
// occurred in array
while (cnt[ele]>0) {
++ele;
}
// If replacement element is greater
// than current arr[i] then visit
// that element for next iteration
if (ele > arr[i] && !vis[arr[i]]) {
vis[arr[i]] = true;
} else {
// Decrement count and assign the element
// to array
--cnt[arr[i]];
arr[i] = ele;
// Increment the replacement count
++replacement;
// Increment element after assigning
// to the array
++ele;
}
}
System.out.print(replacement + "\n");
for (int i = 0; i < n; ++i) {
System.out.print(arr[i] + " ");
}
}
// Driver code
public static void main(String[] args) {
int arr[] = {2, 3, 4, 3, 2};
int sz = arr.length;
lexicoSmallestPermuatation(arr, sz);
}
}
// This code is contributed by 29AjayKumar
Python3
# Python 3 program to print lexicographically
# permutation array by replacing minimum
# element of array
# Function to calculate lexicographically
# permutation in array
def lexicoSmallestPermuatation(arr, n):
# Calculate frequency of array elements
cnt = [0 for i in range(n + 1)]
for i in range(n):
cnt[arr[i]] += 1
ele = 1
replacement = 0
vis = [0 for i in range(n + 1)]
for i in range(n):
# If count of element is 1, no
# need to replace
if (cnt[arr[i]] == 1):
continue
# Find the element that has not
# occurred in array
while (cnt[ele]):
ele += 1
# If replacement element is greater
# than current arr[i] then visit
# that element for next iteration
if (ele > arr[i] and vis[arr[i]] == 0):
vis[arr[i]] = 1;
else:
# Decrement count and assign
# the element to array
cnt[arr[i]] -= 1
arr[i] = ele
# Increment the replacement count
replacement += 1
# Increment element after assigning
# to the array
ele += 1
print(replacement)
for i in range(n):
print(arr[i], end = " ")
# Driver code
if __name__ == '__main__':
arr = [2, 3, 4, 3, 2]
sz = len(arr)
lexicoSmallestPermuatation(arr, sz)
# This code is contributed by
# Shashank_Sharma
C#
// C# program to print lexicographically
// permutation array by replacing minimum
// element of array
using System;
public class GFG {
// Function to calculate lexicographically permutation
// in array
static void lexicoSmallestPermuatation(int []arr, int n) {
// Calculate frequency of array elements
int []cnt= new int[n + 1];
for (int i = 0; i < n; ++i) {
++cnt[arr[i]];
}
int ele = 1, replacement = 0;
bool []vis = new bool[n + 1];
for (int i = 0; i < n; ++i) {
// If count of element is 1, no
// need to replace
if (cnt[arr[i]] == 1) {
continue;
}
// Find the element that has not
// occurred in array
while (cnt[ele]>0) {
++ele;
}
// If replacement element is greater
// than current arr[i] then visit
// that element for next iteration
if (ele > arr[i] && !vis[arr[i]]) {
vis[arr[i]] = true;
} else {
// Decrement count and assign the element
// to array
--cnt[arr[i]];
arr[i] = ele;
// Increment the replacement count
++replacement;
// Increment element after assigning
// to the array
++ele;
}
}
Console.Write(replacement + "\n");
for (int i = 0; i < n; ++i) {
Console.Write(arr[i] + " ");
}
}
// Driver code
public static void Main() {
int []arr = {2, 3, 4, 3, 2};
int sz = arr.Length;
lexicoSmallestPermuatation(arr, sz);
}
}
// This code is contributed by Rajput-Ji//
PHP
$arr[$i] && !$vis[$arr[$i]])
$vis[$arr[$i]] = 1;
else
{
// Decrement count and assign the
// element to array
--$cnt[$arr[$i]];
$arr[$i] = $ele;
// Increment the replacement count
++$replacement;
// Increment element after assigning
// to the array
++$ele;
}
}
echo $replacement. "\n";
for ($i = 0; $i < $n; ++$i)
echo $arr[$i] . " ";
}
// Driver code
$arr = array(2, 3, 4, 3, 2 );
$sz = sizeof($arr);
lexicoSmallestPermuatation($arr, $sz);
// This code is contributed by ita_c
?>
输出
2
1 3 4 5 2
时间复杂度: O(n)