算法-把n个数的每一种排列情况都列出来(排列组合)-全排列-字典序算法(一看就懂)

首先需要介绍字典序算法

比如 236541想找到下一个比它大的数

他有3个步骤

1.从最右边开始找到第一组 左小于右的数 41 54 65 36 23 这样找,很显然,我们找到36就找到了,后面的就不用找了。

2.找到之后立刻交换吗?不是的。定位了这个3以后,再从右边开始找。找第一个比3大的数。那就是4。这时候我们交换3,4

3.交换以后就算完了吗?不是的。还要进行一次排序。交换后是这样的。246531。我们对4(也就是刚才3那个位置)之后进行排序。得出结果为241356

就好了。


原理:其实很简单。从右边找过来,就是为了保证下一个数就真的是比这个数大的下一个数。当找到 左小于右这种情况,就是我们要交换的机会。为什么交换的机会在这里?因为假如说你要强行找一组 左大于右的并且把他换掉,那岂不是越来越小了? 再换个角度思考。236541,你后面都已经倒序了,你觉得23开头还有更大的吗?没了。

可能又有一个问题。那我6541不倒序,比如236154,你怎么解释?那你还是一样去看待。236以后的154,54又是倒序。所以他第一步的目的,就是略过那些倒序,也就是略过已经实现最大的东西。

接下来几步相比也不难理解。


代码:(分为递归和非递归两种方法。虽然是用java写的,但是不影响其他语言的人阅读)

//这里是递归形式方法(传进来的必须是增序的,不然怎么求全序列?)
private static void Lexi(List<Integer> list) {
    int size = list.size();
    //从右往左,找出第一组 左小于右 的数
    //现在 1 2 3 4 5
    int a = -1;
    for (int i = size - 1; i >= 1; i --) {//1.找到并记录第一个左小于右的数
        if (list.get(i - 1) < list.get(i)) {
            a = i - 1;
            break;
        }
    }
    if (a == -1) {
 //执行完了退出递归
        return;
    }

    int b = 0;
    for (int i = size - 1; i > a; i --) {//2.重新开始找,第一个大于我们找到的那个数
        if (list.get(a) < list.get(i)) {
            b = i;
            break;
        }
    }
    List<Integer> newList = new ArrayList<>();
    newList.addAll(list);
    Collections.swap(newList, a, b);//进行交换

    //排序,a + 1到最后都排一次序
    sort(newList, a + 1, size - 1);//最后进行排序

    allList.add(newList)<
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值