博客
关于我
算法笔记_128:完美洗牌算法(Java)
阅读量:435 次
发布时间:2019-03-06

本文共 2951 字,大约阅读时间需要 9 分钟。

问题描述

有一个长度为2n的数组{a1, a2, a3, ..., an, b1, b2, b3, ..., bn},希望排序后变成{a1, b1, a2, b2, a3, b3, ..., an, bn}。请考虑有没有时间复杂度为O(n)而空间复杂度为O(1)的解法。


解决方案

位置置换算法

下面算法的时间复杂度为O(n),空间复杂度为O(n)。

算法代码

package com.liuzhen.practice;public class Main {    public void getLocationReplace(String[] A) {        int len = A.length;        String[] temp = new String[len];        for (int i = 1; i < len; i++) {            temp[(2 * i) % len] = A[i];        }        for (int i = 1; i < len; i++) {            A[i] = temp[i];        }        for (int i = 1; i < len; i = i + 2) {            String a1 = A[i];            A[i] = A[i + 1];            A[i + 1] = a1;        }    }    public static void main(String[] args) {        Main test = new Main();        String[] A = {"", "a1", "a2", "a3", "a4", "a5", "b1", "b2", "b3", "b4", "b5"};        test.getLocationReplace(A);        for (int i = 1; i < A.length; i++) {            System.out.print(A[i] + " ");        }    }}

运行结果

a1 b1 a2 b2 a3 b3 a4 b4 a5 b5

走环算法

下面算法的时间复杂度为O(n),空间复杂度为O(1)。

算法代码

package com.liuzhen.practice;public class Main1 {    public void CycleLeader(String[] A, int start, int mod) {        for (int i = start * 2 % mod; i != start; i = i * 2 % mod) {            String temp = A[i];            A[i] = A[start];            A[start] = temp;        }        return;    }    public void Reverse(String[] A, int start, int end) {        while (start < end) {            String temp = A[start];            A[start++] = A[end];            A[end--] = temp;        }        return;    }    public void RightRotate(String[] A, int start, int m, int n) {        Reverse(A, start + m + 1, start + n);        Reverse(A, start + n + 1, start + n + m);        Reverse(A, start + m + 1, start + n + m);        return;    }    public void PerfectShuffle(String[] A) {        int len = A.length;        int n = (len - 1) / 2;        int start = 0;        while (n > 1) {            int k = 0, m = 1;            for (; (len - 1) / m >= 3; k++, m = m * 3) {            }            m = m / 2;            RightRotate(A, start, m, n);            for (int i = 0, t = 1; i < k; i++, t = t * 3) {                CycleLeader(A, t, m * 2 + 1);            }            start = start + m * 2;            n = n - m;        }        if (n == 1) {            String temp = A[1 + start];            A[1 + start] = A[2 + start];            A[2 + start] = temp;        }        for (int i = 1; i < len; i = i + 2) {            String a1 = A[i];            A[i] = A[i + 1];            A[i + 1] = a1;        }        return;    }    public static void main(String[] args) {        Main1 test = new Main1();        String[] A = {"", "a1", "a2", "a3", "a4", "a5", "b1", "b2", "b3", "b4", "b5"};        test.PerfectShuffle(A);        for (int i = 1; i < A.length; i++) {            System.out.print(A[i] + " ");        }    }}

运行结果

a1 b1 a2 b2 a3 b3 a4 b4 a5 b5

总结

本文探讨了两种排序数组的方法:位置置换算法和走环算法。位置置换算法虽然实现简单,但空间复杂度为O(n)。走环算法实现复杂,但空间复杂度为O(1),更符合用户要求。

转载地址:http://brvyz.baihongyu.com/

你可能感兴趣的文章
Openlayers实战:绘制多边形,导出CSV文件
查看>>
Openlayers实战:绘制带箭头的线
查看>>
Openlayers实战:绘制点、线、圆、多边形
查看>>
Openlayers实战:绘制矩形,正方形,正六边形
查看>>
Openlayers实战:自定义放大缩小,显示zoom等级
查看>>
Openlayers实战:自定义版权属性信息
查看>>
Openlayers实战:输入WKT数据,输出GML、Polyline、GeoJSON格式数据
查看>>
Openlayers实战:选择feature,列表滑动,定位到相应的列表位置
查看>>
Openlayers实战:非4326,3857的投影
查看>>
Openlayers高级交互(1/20): 控制功能综合展示(版权、坐标显示、放缩、比例尺、测量等)
查看>>
Openlayers高级交互(10/20):绘制矩形,截取对应部分的地图并保存
查看>>
Openlayers高级交互(11/20):显示带箭头的线段轨迹,箭头居中
查看>>
Openlayers高级交互(12/20):利用高德逆地理编码,点击位置,显示坐标和地址
查看>>
Openlayers高级交互(13/20):选择左右两部分的地图内容,横向卷帘
查看>>
Openlayers高级交互(14/20):汽车移动轨迹动画(开始、暂停、结束)
查看>>
Openlayers高级交互(15/20):显示海量多边形,10ms加载完成
查看>>
Openlayers高级交互(16/20):两个多边形的交集、差集、并集处理
查看>>
Openlayers高级交互(17/20):通过坐标显示多边形,计算出最大幅宽
查看>>
Openlayers高级交互(18/20):根据feature,将图形适配到最可视化窗口
查看>>
Openlayers高级交互(19/20): 地图上点击某处,列表中显示对应位置
查看>>