📜  K差排列

📅  最后修改于: 2021-04-24 19:07:40             🧑  作者: Mango

给定两个整数n和k。考虑自然n个数的第一个排列,P =“ 1 2 3…n”,打印排列“结果”,使得abs(Result i – P i )= k ,其中P i表示i在排列P中的位置。 P i的范围从1到n。如果有多个可能的结果,则打印按字典顺序最小的结果。

Input: n = 6 k = 3
Output: 4 5 6 1 2 3
Explanation:
     P = 1 2 3 4 5 6
Result = 4 5 6 1 2 3
We can notice that the difference between
individual numbers (at same positions) of 
P and result is 3 and "4 5 6 1 2 3" is 
lexicographically smallest such permutation.
Other greater permutations could be 

Input  : n = 6 k = 2
Output : Not possible
Explanation: No permutation is possible 
with difference is k 

天真的方法是生成从1到n的所有置换,并选择满足绝对差k的最小置换。此方法的时间复杂度为Ω(n!),对于较大的n值,肯定会超时。

高效的方法是观察索引每个位置的模式。对于索引i的每个位置,只能存在两个候选项,即i + k和i – k。由于我们需要找到按字典顺序排列的最小排列,因此我们将首先寻找i-k个候选(如果可能),然后寻找i + k个候选。

Illustration:
 n = 8, k = 2
 P : 1 2 3 4 5 6 7 8

 For any ith position we will check which candidate
 is possible i.e., i + k or i - k 

 1st pos = 1 + 2 = 3 (1 - 2 not possible)
 2nd pos = 2 + 2 = 4 (2 - 2 not possible)
 3rd pos = 3 - 2 = 1 (possible)
 4th pos = 4 - 2 = 2 (possible)
 5th pos = 5 + 2 = 7 (5 - 2 already placed, not possible)
 6th pos = 6 + 2 = 8 (6 - 2 already placed, not possible)
 7th pos = 7 - 2 = 5 (possible)
 8th pos = 8 - 2 = 6 (possible)

注意:如果我们观察上面的插图,我们将发现在k连续间隔之后,i + k和i – k交替出现。另一个观察结果是,整个排列仅在n为偶数时才能将n分为两部分,其中每个部分必须被k整除。

C++
// C++ program to find k absolute difference
// permutation
#include
using namespace std;
  
void kDifferencePermutation(int n, int k)
{
    // If k is 0 then we just print the
    // permutation from 1 to n
    if (!k)
    {
        for (int i = 0; i < n; ++i)
            cout << i + 1 << " ";
    }
  
    // Check whether permutation is feasible or not
    else if (n % (2 * k) != 0)
        cout <<"Not Possible";
  
    else
    {
        for (int i = 0; i < n; ++i)
        {
            // Put i + k + 1 candidate if position is
            // feasible, otherwise put the i - k - 1
            // candidate
            if ((i / k) % 2 == 0)
                cout << i + k + 1 << " ";
            else
                cout << i - k + 1 << " ";
        }
    }
    cout << "\n";
}
  
// Driver code
int main()
{
    int n = 6 , k = 3;
    kDifferencePermutation(n, k);
  
    n = 6 , k = 2;
    kDifferencePermutation(n, k);
  
    n = 8 , k = 2;
    kDifferencePermutation(n, k);
  
    return 0;
}


Java
// Java program to find k absolute
// difference permutation
import java.io.*;
  
class GFG {
  
    static void kDifferencePermutation(int n,
                                    int k)
    {
        // If k is 0 then we just print the
        // permutation from 1 to n
        if (!(k > 0))
        {
            for (int i = 0; i < n; ++i)
                System.out.print( i + 1 + " ");
        }
      
        // Check whether permutation is
        // feasible or not
        else if (n % (2 * k) != 0)
            System.out.print("Not Possible");
      
        else
        {
            for (int i = 0; i < n; ++i)
            {
                // Put i + k + 1 candidate
                // if position is feasible,
                // otherwise put the
                // i - k - 1 candidate
                if ((i / k) % 2 == 0)
                    System.out.print( i + k 
                            + 1 + " ");
                else
                    System.out.print( i - k 
                            + 1 + " ");
            }
        }
        System.out.println() ;
    }
      
    // Driver code
    static public void main (String[] args)
    {
        int n = 6 , k = 3;
        kDifferencePermutation(n, k);
      
        n = 6 ;
        k = 2;
        kDifferencePermutation(n, k);
      
        n = 8 ;
        k = 2;
        kDifferencePermutation(n, k);
    }
}
  
// This code is contributed by anuj_67.


Python3
# Python 3 program to find k 
# absolute difference permutation
def kDifferencePermutation(n, k):
      
    # If k is 0 then we just print the
    # permutation from 1 to n
    if (k == 0):
        for i in range(n):
            print(i + 1, end = " ")
  
    # Check whether permutation
    # is feasible or not
    elif (n % (2 * k) != 0):
        print("Not Possible", end = "")
  
    else:
        for i in range(n):
              
            # Put i + k + 1 candidate if position is
            # feasible, otherwise put the i - k - 1
            # candidate
            if (int(i / k) % 2 == 0):
                print(i + k + 1, end = " ")
            else:
                print(i - k + 1, end = " ")
  
    print("\n", end = "")
  
# Driver code
if __name__ == '__main__':
    n = 6
    k = 3
    kDifferencePermutation(n, k)
  
    n = 6
    k = 2
    kDifferencePermutation(n, k)
  
    n = 8
    k = 2
    kDifferencePermutation(n, k)
      
# This code is contributed by
# Surendra_Gangwar


C#
// C# program to find k absolute
// difference permutation
using System;
  
class GFG {
  
    static void kDifferencePermutation(int n,
                                       int k)
    {
        // If k is 0 then we just print the
        // permutation from 1 to n
        if (!(k > 0))
        {
            for (int i = 0; i < n; ++i)
                Console.Write( i + 1 + " ");
        }
      
        // Check whether permutation is
        // feasible or not
        else if (n % (2 * k) != 0)
            Console.Write("Not Possible");
      
        else
        {
            for (int i = 0; i < n; ++i)
            {
                // Put i + k + 1 candidate
                // if position is feasible,
                // otherwise put the
                // i - k - 1 candidate
                if ((i / k) % 2 == 0)
                    Console.Write( i + k 
                              + 1 + " ");
                else
                    Console.Write( i - k 
                              + 1 + " ");
            }
        }
        Console.WriteLine() ;
    }
      
    // Driver code
    static public void Main ()
    {
        int n = 6 , k = 3;
        kDifferencePermutation(n, k);
      
        n = 6 ;
        k = 2;
        kDifferencePermutation(n, k);
      
        n = 8 ;
        k = 2;
        kDifferencePermutation(n, k);
    }
}
  
// This code is contributed by anuj_67.


PHP


输出:

4 5 6 1 2 3 
Not Possible
3 4 1 2 7 8 5 6 

时间复杂度: O(n)
辅助空间: O(1)