• [leetcode]Permutation Sequence


    这道题用DFS加计数肯定是可以做的,但是我忽然想不起下一个排列的非递归做法了。后来在网上找到如下:http://blog.csdn.net/morewindows/article/details/7370155

    如何计算字符串的下一个排列了?来考虑"926520"这个字符串,我们从后向前找第一双相邻的递增数字,"20"、"52"都是非递增的,"26 "即满足要求,称前一个数字2为替换数,替换数的下标称为替换点,再从后面找一个比替换数大的最小数(这个数必然存在),0、2都不行,5可以,将5和2交换得到"956220",然后再将替换点后的字符串"6220"颠倒即得到"950226"。

    回到这道题目,显然有数学方法可以做的。其实就是计算n位时,先算出后面的数的排列的数量(n-1)!,然后除一下,就能得到n在剩余的排列里的位置了。http://www.abcoding.info/?p=805

    假设集合为[1,2,3,4],求出第6个组合。
    第6个组合对应的下标为5(下标从0开始),我们首先求出5所对应的lehmer码:
    5/3! = 0 余5
    5/2! = 2 余1
    1/1! = 1 余0
    0 (lehmer code最后一位总为0)
    所以所求lehmer码为0210

    当前集合对应的序列为1234
    接下来将lehmer码中的每个数字当做当前序列的下标,下标0对应的集合元素为1,当前序列变成234;下标2对应的集合元素为4,当前序列变成23;下标1对应的集合元素为3,当前序列变成2;下标0对应的元素为2
    所以所求的组合即为1432

    实现上要注意的是:1. lehmer码最后一位总是0;2. k也是从0开始,所以要k--;

    import java.util.*;
    public class Solution {
        public String getPermutation(int n, int k) {
            k--; // start from index 0
            ArrayList<Integer> arr = new ArrayList<Integer>();
            ArrayList<Integer> pos = new ArrayList<Integer>();
            for (int i = 1; i <= n; i++)
            {
                arr.add(i);
            }
            int factor = 1;
            for (int i = 1; i < n; i++)
            {
                factor *= i;
            }
            for (int i = n-1; i >= 1; i--)
            {
                pos.add(k / factor);
                k = k % factor;
                factor /= i;
            }
            pos.add(0);
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < pos.size(); i++)
            {
                int p = pos.get(i);
                sb.append(arr.get(p));
                arr.remove(p);
            }
            return sb.toString();
        }
    }
    

    第二遍:

    其实这道题是将(K-1,因为从1开始)分解成A*(n-1)!+B*(n-2)!+...+X*(1)!,然后A,B,C,...都是在剩余数组的位置。这样的话,就可以通过辗转除法得到这些系数,然后在剩余的数组中去得到该元素,加到字符串后面。Annie的解法更直观:https://github.com/AnnieKim/LeetCode/blob/master/PermutationSequence.h

    class Solution {
    public:
        string getPermutation(int n, int k) {
            int factorial = 1;
            for (int i = 1; i <= n; i++)
            {
                factorial *= i;
            }
            
            string result;
            result.resize(n);
            for (int i = 0; i < n; i++)
            {
                result[i] = i + '1';
            }
            
            k--;
            for (int i = 0; i < n; i++)
            {
                factorial /= (n - i);
                int idx = k / factorial;
                for (int j = i + idx; j < n && j > i; j--)
                {
                    swap(result[j], result[j-1]);
                }
                k %= factorial;
            }
            return result;
        }
    };
    

      

  • 相关阅读:
    c/c++:字符串输入输出流
    POJ 1036Gangsters【DP】
    POJ 1157LITTLE SHOP OF FLOWERS【DP】
    一个月后....
    http://poj.org/problem?id=1258
    POJ 2677 Tour【DP】
    POJ 1160Post Office【DP】
    C基础
    linux面试fork函数题
    linux学习
  • 原文地址:https://www.cnblogs.com/lautsie/p/3352778.html
Copyright © 2020-2023  润新知