Algorithm leetcode|60. Permutation sequence (rust punches hard)



60. Permutation sequence:

Given a set , there are permutations [1,2,3,...,n]of all its elements .n!

List all permutations in order of size and mark them one by one. n = 3When , all permutations are as follows:

"123"
"132"
"213"
"231"
"312"
"321"

Given nand k, return the kpermutation.

Example 1:

输入:
	
	n = 3, k = 3
	
输出:
	
	"213"

Example 2:

输入:
	
	n = 4, k = 9
	
输出:

	"2314"

Example 3:

输入:
	
	n = 3, k = 1
	
输出:
	
	"123"

hint:

  • 1 <= n <= 9
  • 1 <= k <= n!

analyze:

  • Facing this algorithm problem, the second leader fell into deep thought again.

  • If you simulate and generate k sequences in sequence, the efficiency is too low.

  • You need to find the rules and directly generate the results. At this time, you need to use a little mathematical knowledge, not advanced mathematics, but the knowledge of permutations and combinations. It should be high school knowledge, or it may be junior high school knowledge. In short, you must know:

    1. nElements are permuted, and the total number of permutations is n!.
  • It can be deduced that if there is nan element arrangement, then the first position will be (n - 1)!replaced by the next element after the second arrangement.

  • For example 4, elements [1, 2, 3, 4]are arranged, the first position is 1 first, and after 3 * 2 * 1the arrangement (that is, 3the total number of elements arranged 3!), the first position starts to be arranged 2, that is:

    1. 1234
    2. 1243
    3. 1324
    4. 1342
    5. 1423
    6. 1432
    7. 2134
  • So we can directly use (k - 1) / (n - 1)! + 1to calculate which element the first position is.

  • And then calculating the element at the second position is actually similar to calculating the element at the first position. The only difference is that the element at the first position has already been occupied, so it needs to be excluded later, so which one should be recorded The element has been used, which element has not been used, and the following are the same sub-problems.


answer:

rust:

impl Solution {
    
    
    pub fn get_permutation(n: i32, k: i32) -> String {
    
    
        let n = n as usize;
        let mut k = k as usize;

        // 结果
        let mut ans = String::new();

        // 阶乘缓存不同排列数
        let mut factorial = vec![0; n];
        factorial[0] = 1;
        (1..n).for_each(|i| {
    
    
            factorial[i] = factorial[i - 1] * i;
        });
        // 排列从0编号,便于后面计算
        k -= 1;
        // 1为有效还没有占用,0为无效已经被占用
        let mut valid = vec![1; n + 1];
        (1..n + 1).for_each(|i| {
    
    
            // 计算当前位置的数字是第几个没被占用的数字
            let mut order = k / factorial[n - i] + 1;
            for j in 1..n + 1 {
    
    
                // 取得数字
                order -= valid[j];
                if order == 0 {
    
    
                    ans.push((j as u8 + b'0') as char);
                    valid[j] = 0;
                    break;
                }
            }
            // 余数为下级子排列的序号
            k %= factorial[n - i];
        });

        return ans;
    }
}

go:

func getPermutation(n int, k int) string {
    
    
    // 结果
	ans := ""

	// 阶乘缓存不同排列数
	factorial := make([]int, n)
	factorial[0] = 1
	for i := 1; i < n; i++ {
    
    
		factorial[i] = factorial[i-1] * i
	}
	// 排列从0编号,便于后面计算
	k--
	// 1为有效还没有占用,0为无效已经被占用
	valid := make([]int, n+1)
	for i := 0; i < len(valid); i++ {
    
    
		valid[i] = 1
	}
	for i := 1; i <= n; i++ {
    
    
		// 计算当前位置的数字是第几个没被占用的数字
		order := k/factorial[n-i] + 1
		for j := 1; j <= n; j++ {
    
    
			// 取得数字
			order -= valid[j]
			if order == 0 {
    
    
				ans += strconv.Itoa(j)
				valid[j] = 0
				break
			}
		}
		// 余数为下级子排列的序号
		k %= factorial[n-i]
	}

	return ans
}

c++:

class Solution {
    
    
public:
    string getPermutation(int n, int k) {
    
    
        // 结果
        string ans;

        // 阶乘缓存不同排列数
        vector<int> factorial(n);
        factorial[0] = 1;
        for (int i = 1; i < n; ++i) {
    
    
            factorial[i] = factorial[i - 1] * i;
        }
        // 排列从0编号,便于后面计算
        --k;
        // 1为有效还没有占用,0为无效已经被占用
        vector<int> valid(n + 1, 1);
        for (int i = 1; i <= n; ++i) {
    
    
            // 计算当前位置的数字是第几个没被占用的数字
            int order = k / factorial[n - i] + 1;
            for (int j = 1; j <= n; ++j) {
    
    
                // 取得数字
                order -= valid[j];
                if (!order) {
    
    
                    ans += (j + '0');
                    valid[j] = 0;
                    break;
                }
            }
            // 余数为下级子排列的序号
            k %= factorial[n - i];
        }
        
        return ans;
    }
};

python:

class Solution:
    def getPermutation(self, n: int, k: int) -> str:
        # 结果
        ans = list()
        # 阶乘缓存不同排列数
        factorial = [1]
        for i in range(1, n):
            factorial.append(factorial[-1] * i)
        # 排列从0编号,便于后面计算
        k -= 1
        # 1为有效还没有占用,0为无效已经被占用
        valid = [1] * (n + 1)
        for i in range(1, n + 1):
            # 计算当前位置的数字是第几个没被占用的数字
            order = k // factorial[n - i] + 1
            for j in range(1, n + 1):
                # 取得数字
                order -= valid[j]
                if order == 0:
                    ans.append(str(j))
                    valid[j] = 0
                    break
            # 余数为下级子排列的序号
            k %= factorial[n - i]

        return "".join(ans)


java:

class Solution {
    
    
    public String getPermutation(int n, int k) {
    
    
        // 结果
        final StringBuilder ans = new StringBuilder();
        // 阶乘缓存不同排列数
        final int[] factorial = new int[n];
        factorial[0] = 1;
        for (int i = 1; i < n; ++i) {
    
    
            factorial[i] = factorial[i - 1] * i;
        }
        // 排列从0编号,便于后面计算
        --k;
        // 1为有效还没有占用,0为无效已经被占用
        final int[] valid = new int[n + 1];
        Arrays.fill(valid, 1);
        for (int i = 1; i <= n; ++i) {
    
    
            // 计算当前位置的数字是第几个没被占用的数字
            int order = k / factorial[n - i] + 1;
            for (int j = 1; j <= n; ++j) {
    
    
                // 取得数字
                order -= valid[j];
                if (order == 0) {
    
    
                    ans.append(j);
                    valid[j] = 0;
                    break;
                }
            }
            // 余数为下级子排列的序号
            k %= factorial[n - i];
        }

        return ans.toString();
    }
}

Thank you very much for reading this article~
Welcome to 【Like】【Favorite】【Comment】Walk three times in a row~ It
is not difficult to give up, but it must be cool to persevere~
I hope we all can improve a little every day~
This article is written by the white hat of the second master: https://le-yi.blog.csdn.net/Blog original~


Guess you like

Origin blog.csdn.net/leyi520/article/details/131471288
Recommended