C++ STL之next_permutation小证明与Java实现

C++ STL之next_permutation小证明与Java实现

最近在用Java写程序时,会经常涉及到生成排列之类,在C++ STL里面有next_permutation 这个函数,可在Java里的确没有这个函数的实现,于是自己对next_permutation稍微理顺了一下。

next_permutation实现思路:
在当前序列中,从尾端向前寻找两个相邻元素,前一个记为*i,后一个记为*j,并且满足*i < *j。然后再从尾端寻找另一个元素*t,如果满足*i < *t,即将第i个元素与第t个元素对调,并将第j个元素之后(包括j)的所有元素颠倒排序,即求出下一个序列了。

自己的小证明如下:

  • 例如: 1 3 4 5 2
    这个序列首先从尾部找到两相邻元素i, j, i=2,j=3, 同时t=j, 即i, j之后都为逆序,所以显然就是i与j交换才能得到下一个序列。

  • 例如:1 5 7 6 4 3 2
    这个序列,对应的i=2, j=3, 但从尾部向前寻找元素t时, t!=j, 即*t > *i && *t < *j,所以这样子*t肯定是在位置j之后大于*i的元素中的最小值,所以*i与*t交换、j之后的元素逆序排列是能够得到下一个序列的。

一个排列一个具有N个元素的代码:

package lanqiao;

    import java.util.ArrayList;

    public class PREV_2 {
        static int[] array = new int[10];
        static void reverse(int begin, int end) {
            int mid = (begin+end) / 2;
            int cnt = 0;
            for(; ;) {
                if(cnt > mid-begin) break;
                int t = array[begin+cnt]; array[begin+cnt] = array[end-cnt]; array[end-cnt] = t;
                cnt++;
            }
        }
        static boolean next_per(int begin, int end) {
            if(begin == end)  return false;   //为空
            if(begin+1 == end) return false;  //只有一个元素
            int i = end;
            for(; ;) {
                int j = i; --i;
                if(array[i] < array[j]) {                 //前<后   相邻
                    int t = end;
                    while(array[i] >= array[t]) {
                        --t;
                    }

                    //System.out.println(array[i] +"~"+ array[t]);
                    int temp = array[i]; array[i] = array[t]; array[t] = temp;
                    reverse(j, end);
                    return true;
                }
                if(i == begin) {              //前一元素已经指向首元素,反转整个区间,无下一元素    dcba的下一个排列是abcd
                    reverse(begin, end);
                    return false;
                }
            }
        }

        public static void main(String[] args) {
            array[1] = 1; array[2] = 2; array[3] = 3; array[4] = 4; array[5] = 5; array[6] = 6;
            array[7] = 7; array[8] = 8; array[9] = 9; 
            while(next_per(1, 9)) {
                for(int i = 1;i <= 9;i++) {
                    System.out.print(array[i]+" ");
                }
                System.out.println();
            }
        }
    }

p.s本文是我第一次采用MarkDown撰写

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值