首先需要介绍字典序算法
比如 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)<