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)
上一篇 2022年4月7日 上午6:20
下一篇 2022年4月7日 上午6:20


相关推荐

  • 最好用的java开发工具_应用开发工具

    最好用的java开发工具_应用开发工具Java开发者常常都会想办法如何更快地编写Java代码,让编程变得更加轻松。目前,市面上涌现出越来越多的高效编程工具。所以,以下总结了一系列工具列表,其中包含了大多数开发人员已经使用、正在使用或

    2022年8月3日
    7
  • 数据库表的约束条件[通俗易懂]

    数据库表的约束条件[通俗易懂]1.主键约束主键约束可以用两种方式定义:列级主键约束和表级主键约束列级主键约束演示:createtabledept_htlwk(deptnovarchar(20)primarykey,–列级约束条件dnamevarchar(20),locationvarchar(40));表级主键约束演示:createtabledept_htlwk(deptnovarchar(20),dnamevarchar(20),locationvarchar(40),

    2022年10月13日
    3
  • 简易旋转倒立摆及控制系统实现方案_自动旋转装置怎么做

    简易旋转倒立摆及控制系统实现方案_自动旋转装置怎么做摘要本系统是基于TM4单片机来完成各项功能的,实现了一套简易旋转倒立摆及其控制装置。旋转倒立摆的结构如图1所示。电动机A固定在支架B上,通过转轴F驱动旋转臂C旋转。摆杆E通过转轴D固定在旋转臂C的一端,当旋转臂C在电动机A驱动下作往复旋转运动时,带动摆杆E在垂直于旋转臂C的平面作自由旋转。其中系统的驱动采用了Mos管电机驱动;姿态获取通过角度传感器;控制部分采用PID算法,实现题目在角度等的精度要求和及时性;该系统通过串口通信来进行PID各参数的串口调

    2022年8月18日
    15
  • html5文字云在线制作,用Tagxedo在线制作个性化词云

    html5文字云在线制作,用Tagxedo在线制作个性化词云原标题 用 Tagxedo 在线制作个性化词云词云 或者叫文字云 就是对网络文本中出现频率较高的 关键词 予以视觉上的突出 形成 关键词云层 或 关键词渲染 从而过滤掉大量的文本信息 使浏览网页者只要一眼扫过文本就可以领略文本的主旨 沈浩老师曾在搜狐博客分享过一篇关于词云制作的文章 详细的描述了个性化词云制作的思路和工具 今天小兵也来学习一下如何用 Tagxedo 在线制作个性化词云 在线制作词云工具

    2026年3月19日
    2
  • 【SpringBoot】36、SpringBoot整合Redis实现发布/订阅

    【SpringBoot】36、SpringBoot整合Redis实现发布/订阅一 简介 1 发布订阅 SUBSCRIBE UNSUBSCRIBE 和 PUBLISH 实现了发布 订阅消息范例 发送者 publishers 不用编程就可以向特定的接受者发送消息 subscribers Rather 发布的消息进入通道 不需要知道有没有订阅者 订阅者发表感兴趣的一个或多个通道 并且只接受他们感兴趣的消息 不管发布者是不是存在 发布者和订阅者的解耦可以允许更大的伸缩性和更多动态的网络拓扑 2 说明本篇文章是继 SpringBoot 三十四 SpringBoot

    2026年3月19日
    3
  • pytest parametrize fixture_参数化查询

    pytest parametrize fixture_参数化查询前言当某个接口中的一个字段,里面规定的范围为1-5,你5个数字都要单独写一条测试用例,就太麻烦了,这个时候可以使用pytest.mark.parametrize装饰器可以实现测试用例参数化。官方示

    2022年7月31日
    8

发表回复

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

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