📌  相关文章
📜  按最小字法替换的具有不同元素的按字典顺序排列的最小排列

📅  最后修改于: 2021-04-29 06:39:05             🧑  作者: Mango

给定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,以便我们可以在下一次迭代中替换它。之所以需要执行此步骤,是因为我们需要对字典进行最小的排列

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)