zoukankan      html  css  js  c++  java
  • 算法笔记_128:完美洗牌算法(Java)

    目录

    1 问题描述

    2 解决方案

    2.1位置置换算法

    2.2 走环算法

     


    1 问题描述

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


    2 解决方案

    2.1位置置换算法

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

    具体代码如下:

    package com.liuzhen.practice;
    
    public class Main {
        //对于数组A第i个位置的元素都最终换到了2*i % len的位置
        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;
            }
            return;
        }
        
        
        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 

    2.2 走环算法

    下面算法的时间复杂度为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) {
                //第1步:找到2*m = 3^k - 1,使得3^k <= len - 1 < 3^(k + 1)
                int k = 0, m = 1;
                for(;(len - 1) / m >= 3;k++, m = m * 3);
                m = m / 2;
            
                //第2步:把数组中的A[m + 1,...,n + m]那部分循环右移m位
                RightRotate(A, start, m, n);
                
                //第3步:对于长度为2*m的数组,刚好有k个圈,每个圈的头部为3^i
                for(int i = 0, t = 1;i < k;i++, t = t * 3)
                    CycleLeader(A, t, m * 2 + 1);
                
                //第4步:对数组后面部分A[2m + 1,...,2n]继续递归上面3步
                start = start + m * 2;
                n = n - m;
                
            }
            //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 

     

    参考资料:

       1.《编程之法面试和算法心得》  July

  • 相关阅读:
    linux下shell显示-bash-4.1#不显示路径解决方法
    update chnroute
    An error "Host key verification failed" when you connect to other computer by OSX SSH
    使用dig查询dns解析
    DNS被污染后
    TunnelBroker for EdgeRouter 后记
    mdadm详细使用手册
    关于尼康黄的原因
    Panda3d code in github
    Python实例浅谈之三Python与C/C++相互调用
  • 原文地址:https://www.cnblogs.com/liuzhen1995/p/6710029.html
Copyright © 2011-2022 走看看