美文网首页
组合数学与算法题-排列组合篇

组合数学与算法题-排列组合篇

作者: rosewind | 来源:发表于2019-01-19 15:51 被阅读0次

前言

之前刷过一些leetcode的题目,这学期修了组合数学这门课,让我感受颇多。课程上更关注的是数学上的解法,并没有讲到具体的用某种语言实现,并没有深入地讲为什么这样做就是对的。结合我的经验,想分享一下我的理解。

leetcode 31.下一个全排列

31.下一个全排列

2个关键点:

  • 下一个全排列比当前的大(字典序)

  • 增量要是最小的

一些例子:

  • 1243 -> 1324,要使1243更大,从右往左看,43已经是最大的了,所以下一个肯定是13开头,故交换2,3得到1342,后2位42肯定无法保证增量最小,故翻转42,得到1324,即为所求

  • 4321 -> 1234,从右往左看,全部递增,故这是最后一个序列了,翻转整个序列,得到1234,符合题目的要求


class Solution {

    public void nextPermutation(int[] nums) {

        if(nums == null || nums.length ==  1) return;

        //从右向左,找到破坏递增规律的第一个数

        int n = nums.length;

        int index = -1;

        for(int i = n-2; i >= 0; i--){

            if(nums[i] < nums[i+1]){

                index = i;

                break;

            }

        }

        //找到比nums[index]大的第一个数

        //交换nums[index]与这个nums[i]

        if(index != -1){

            for(int i = n-1; i>= 0; i--){

            if(nums[i] > nums[index]){

                int tmp = nums[i];

                nums[i] = nums[index];

                nums[index] = tmp;

                break;

            }

        }

        }

        //翻转数组,范围为[index+1,n-1],这样便使增量最小

        //如果是最后一个排列,如[3,2,1],index为-1,翻转整个序列

        reverseArray(nums, index+1, n-1);

    }

    public void reverseArray(int[] nums,int start,int end){

        for(int i = start, j = end;i <= j; i++,j--){

            //交换nums[i]与nums[j]

            int tmp = nums[i];

            nums[i] = nums[j];

            nums[j] = tmp;

        }

    }

}

leetcode 60.第k个全排列

leetcode 60.第k个全排列

n=3时,共有3!个排列

  1. 123

  2. 132

  3. 213

  4. 231

  5. 312

  6. 321

关键:

  • 每2个看成一组,每一组内第一位都是相同的,如123,132

  • 即每n-1个看成一组,总共有n组(n!=n*(n-1))

  • 若第0位已确定,剩下就是n-1个数的排列,可分成n-1组,每个组内(n-2)!个

以n=3,k=4为例:

  • 为了跟程序里的小标对应,从0开始,k=k-1=3

  • 3/2!=1余1,说明第0位是[1,2,3]中下标为1的数,即2

  • 余数为1,剩下2个数,1/1!=1余0,[1,3]中下标为1的数即3

  • 只剩下1,故结果是231

这其实可以归纳出一个数学公式,康托展开与逆展开


class Solution {

    public String getPermutation(int n, int k) {

        //需要用到一点数学知识,康托展开

        StringBuilder sb = new StringBuilder();

        List<Integer> info = new ArrayList<Integer>();

        for(int i=1;i<=n;i++){

            info.add(i);

        }

        int factor=1;

        k=k-1;

        //计算出(k-1)!

        for(int i = 2;i<=n-1;i++){

            factor *= i;

        }

        for(int i=n-1;i>=1;i--){

            int p = k/factor;//商

            k = k%factor;//余数

            sb.append(info.get(p));

            //移除

            info.remove(p);

            //更新

            factor /= i;

        }

        sb.append(info.get(0));//最后info中只剩下一个

        return sb.toString();

    }

}

已知全排列求k

给出231,求k

如果真的理解了上面的分组,很容易就可以列出式子:

1*2!+1*1!=3

因为我们小标从0开始,最后再加1即可

理解一下这个式子的含义:就是求比231小的排列有多少个

只有这几种可能{1, ,}(以1开头的排列,共有2个)

{2,1,}(以2,1,开头的排列,只有1个)

所以231是排在第4的

相关文章

  • 组合数学与算法题-排列组合篇

    前言 之前刷过一些leetcode的题目,这学期修了组合数学这门课,让我感受颇多。课程上更关注的是数学上的解法,并...

  • 排列组合-js

    排列组合 数学相关知识:5分钟彻底了解排列组合 参考:程序员必备算法——排列组合 排列有序,组合无序 3选2 :排...

  • 算法题面试题①-排列组合问题(母函数和卡特兰数)

    母函数 对于一般的排列组合算法题, 可首先尝试通过母函数来解决。 在数学中,某个序列的母函数(Generating...

  • 有重复字符串的排列组合(golang)

    原题:有重复字符串的排列组合 与无重复字符串的排列组合(golang)类似,只是由于golang没有set,需要把...

  • 搜索-组合

    刷题学习的第一类算法,由深度优先搜索DFS引申出的,排列组合算法。在一个给定长度n的数组中取出k个数,做组合或者排...

  • m选n组合

    最近需求,要写排列组合算法,首先第一步是m个元素中选n个元素进行组合,也就是数学中C(m,n);方法有多种。 递归...

  • 970. 强整数(Python)

    更多精彩内容,请关注【力扣简单题】。 题目 难度:★★☆☆☆类型:数学,排列组合 给定两个正整数 x 和 y,如果...

  • 排列穷举算法

    今天看到一篇博文 玩个算法题:1-5的排列组合问题 觉得挺有意思。鉴于博主写的是死代码,于是决定自己实现一个动态排...

  • 920. Number of Music Playlists

    排列组合 + DP这道题即考了排列组合的知识又考了DP的知识。这道题的难点在于两处。1。 DP的定义2。DP 的递...

  • 排列组合问题

    为什么要写这篇文章 排列组合问题在数学中占有重要的地位,其与概率论也有密切的关系。而且排列组合问题大量出现在求职笔...

网友评论

      本文标题:组合数学与算法题-排列组合篇

      本文链接:https://www.haomeiwen.com/subject/vdlzdqtx.html