Java实现完美洗牌算法

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)。packagecom.liuzhen.practice;publiccl…

大家好,又见面了,我是你们的朋友全栈君。

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 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/126209.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • PHP 遍历数组的方法汇总

    PHP 遍历数组的方法汇总

    2022年3月12日
    44
  • RSA算法简述

    RSA算法简述52tangzongb+TR/9sbreGJhbKT5U5rQCTUebfRngB0uhNMnvMClf0f/IpPTsM5+7zWJyT9drzVKzV4oR0J8lyMSWepKvv3BR/3Ab6vC8dmo7NDbzuDtLaDLYhYG+bggQNVvuA5C3TolntxdL4+mGZwfd86WoznJM+Y5TO/0C5MSxvaAMTMZuga7yyBKTH4Wl+7GFHDDZqAXmvPHW/Dz0i45vlToz/+E/RnznY5dBhkw3nnNoNsJIutAUDm4T18J

    2022年6月18日
    34
  • 推荐几个非常不错的富文本编辑器

    推荐几个非常不错的富文本编辑器1、wangEditor——基于javascript和css开发的Web富文本编辑器,轻量、简洁、界面美观、易用、开源免费。界面截图:官网地址2、TinyMCE——TinyMCE是一个轻量级的基于浏览器的所见即所得编辑器,由JavaScript写成。它对IE6+和Firefox1.5+都有着非常良好的支持。功能齐全,界面美观,就是文档是英文的,对开发人员英文水平有一定要求。界面…

    2022年6月10日
    226
  • vuex里mapState,mapGetters使用详解

    vuex里mapState,mapGetters使用详解这次给大家带来vuex里mapState,mapGetters使用详解,vuex里mapState,mapGetters使用的注意事项有哪些,下面就是实战案例,一起来看一下。一、介绍vuex里面的四大金刚:State,Mutations,Actions,Getters(上次记得关于vuex笔记http://www.jb51.net/article/138229.htm,是一个简…

    2022年5月6日
    47
  • Android数据库框架——GreenDao轻量级的对象关系映射框架,永久告别sqlite

    Android数据库框架——GreenDao轻量级的对象关系映射框架,永久告别sqlite

    2021年9月16日
    60
  • Linux vim退出_怎么关闭vim

    Linux vim退出_怎么关闭vim有些终端在vim退出后可以恢复到打开vim前终端的状态,类似这样:$vim/etc/sysconfig/####这里表示打开vim#####sdskk,一些文件内容:q$vim/etc/sysconfig/##终端恢复到先前状态但是有些不行,解决这个问题需要以下两步:1、设置TERM环境变量为xterm或者xterm-color,可以在.ba…

    2022年8月24日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号