zoukankan      html  css  js  c++  java
  • 0060. Permutation Sequence (M)

    Permutation Sequence (M)

    题目

    The set [1,2,3,...,*n*] contains a total of n! unique permutations.

    By listing and labeling all of the permutations in order, we get the following sequence for n = 3:

    1. "123"
    2. "132"
    3. "213"
    4. "231"
    5. "312"
    6. "321"

    Given n and k, return the kth permutation sequence.

    Note:

    • Given n will be between 1 and 9 inclusive.
    • Given k will be between 1 and n! inclusive.

    Example 1:

    Input: n = 3, k = 3
    Output: "213"
    

    Example 2:

    Input: n = 3, k = 3
    Output: "213"
    

    题意

    按字典序输出一个递增序列的第k个排列。

    思路

    对于n个数的排列,只有当后面n-1个数完成一次全排列后,才会对第一个数进行更替,即更换周期cycle为(n-1)!,且第一个数字是按照n个数中从最小数到最大数依次更替的。令 (count=frac{k-1}{cycle}+1),则排在第一位的数字是这n个数中的第count大,将该数字加入结果序列。每次得到第一位数字后,缩小n的规模求剩下n-1个数中应当排在第一位的数,同时要更新n-1个数中要求的第k个排列 (k=(k-1) \% cycle+1)

    笨办法:也可以结合 0031. Next Permutation,从递增序列开始依次计算下一个排列。


    代码实现

    Java

    公式计算

    class Solution {
        public String getPermutation(int n, int k) {
            StringBuilder ans = new StringBuilder();
            boolean[] used = new boolean[n];		//标记剩下的数字
    
            while (n >= 1) {
                // 注意n=1时实际周期为0,将其周期设为1便于合并处理
                int cycle = n == 1 ? 1 : factorial(n - 1);
                int count = (k - 1) / cycle + 1;
                
                // 找到剩余数字中的第count大,并将其加入结果序列
                for (int i = 0; i < used.length; i++) {
                    if (!used[i]) {
                        if (count == 1) {
                            ans.append(i + 1);
                            used[i] = true;
                            break;
                        }
                        count--;
                    }
                }
                
                // 缩小待排列序列的规模
                n--;
                k = (k - 1) % cycle + 1;
            }
    
            return ans.toString();
        }
    
        private int factorial(int n) {
            int ans = 1;
            while (n != 1) {
                ans *= n--;
            }
            return ans;
        }
    }
    

    nextPermutation

    class Solution {
        public String getPermutation(int n, int k) {
            char[] a = new char[n];
            for (int i = 0; i < n; i++) {
                a[i] = (char) (i + 1 + '0');
            }
            int count = 1;
            while (count < k) {
                nextPermutation(a);
                count++;
            }
            return String.valueOf(a);
        }
    
        // 依照当前排列计算下一个排列
        private void nextPermutation(char[] a) {
            int i = a.length - 2;
            while (i >= 0 && a[i] >= a[i + 1]) {
                i--;
            }
            // i==-1说明整个数组是逆序排列,已经是字典序中的最后一个排列
            if (i == -1) {
                return;
            }
            int j = a.length - 1;
            while (a[j] <= a[i]) {
                j--;
            }
            swap(a, i, j);
            reverse(a, i + 1, a.length - 1);
        }
    
        private void reverse(char[] a, int left, int right) {
            while (left < right) {
                swap(a, left++, right--);
            }
        }
    
        private void swap(char[] a, int i, int j) {
            char temp = a[i];
            a[i] = a[j];
            a[j] = temp;
        }
    }
    

    JavaScript

    公式计算

    /**
     * @param {number} n
     * @param {number} k
     * @return {string}
     */
    var getPermutation = function (n, k) {
      let used = new Array(n)
      let ans = ''
    
      while (n > 0) {
        let cycle = n === 1 ? 1 : factorial(n - 1)
        let rank = Math.trunc((k - 1) / cycle) + 1
        let count = 0
        for (let i = 0; i < used.length; i++) {
          if (!used[i]) {
            count++
            if (count === rank) {
              ans += i + 1
              used[i] = true
              break
            }
          }
        }
        k = ((k - 1) % cycle) + 1
        n--
      }
    
      return ans
    }
    
    let factorial = function (n) {
      return n === 1 ? n : n * factorial(n - 1)
    }
    

    nextPermutation

    /**
     * @param {number} n
     * @param {number} k
     * @return {string}
     */
    var getPermutation = function (n, k) {
      let count = 1
      let arr = new Array(n).fill(0).map((v, index) => index + 1)
      while (count !== k) {
        nextPermutation(arr)
        count++
      }
      return arr.join('')
    }
    
    let nextPermutation = function (arr) {
      let i = arr.length - 2
      while (i >= 0 && arr[i] >= arr[i + 1]) {
        i--
      }
      if (i === -1) {
        return
      }
      let j = arr.length - 1
      while (arr[i] >= arr[j]) {
        j--
      }
      [arr[i], arr[j]] = [arr[j], arr[i]]
      let left = i + 1,
        right = arr.length - 1
      while (left < right) {
        [arr[left++], arr[right--]] = [arr[right], arr[left]]
      }
    }
    
  • 相关阅读:
    uva11916 Emoogle Grid (BSGS)
    2016vijos 1-2 股神小L(堆)
    bzoj千题计划311:bzoj5017: [Snoi2017]炸弹(线段树优化tarjan构图)
    Oracle Profile 使用详解--zhuanzai
    通过srvctl add命令添加database信息到srvctl管理器-转
    Oracle Dataguard Standby Redo Log的两个实验
    MySQL数据的主从复制、半同步复制和主主复制详解-转
    解决oralce 11g dg搭建报错:ORA-16664、ORA-16714、ORA-16810问题--转
    oracle分布式事务总结-转载
    日志挖掘Logmnr
  • 原文地址:https://www.cnblogs.com/mapoos/p/13258672.html
Copyright © 2011-2022 走看看