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

Java实现完美洗牌算法的更多相关文章

  1. 算法笔记_128:完美洗牌算法(Java)

    目录 1 问题描述 2 解决方案 2.1位置置换算法 2.2 走环算法   1 问题描述 有一个长度为2n的数组{a1,a2,a3,...,an,b1,b2,b3,...,bn},希望排序后变成{a1 ...

  2. [转]完美洗牌(Perfect Shuffle)问题

    [转]原博文地址:https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/02.09.md ...

  3. 完美洗牌&洗牌

    完美洗牌问题,给定一个数组a1,a2,a3,...an,b1,b2,b3..bn,把它最终设置为b1,a1,b2,a2,...bn,an这样的. O(n)的算法,O(n)的空间. 对于前n个数,映射为 ...

  4. knuth洗牌算法

    首先来思考一个问题: 设计一个公平的洗牌算法 1. 看问题,洗牌,显然是一个随机算法了.随机算法还不简单?随机呗.把所有牌放到一个数组中,每次取两张牌交换位置,随机 k 次即可. 如果你的答案是这样, ...

  5. 洗牌算法Fisher_Yates原理

    1.算法 http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle 简单的原理如下图所示: 2.原理 总结下,洗牌算法Fisher_Yates ...

  6. C# 洗牌算法

    最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来. 十年河东十年河西,莫欺少年穷 学无止境,精益求精   C#洗牌算法如下: class Program { ...

  7. js 随机数 洗牌算法

    function shuffle(arr){ var len = arr.length; for(var i = 0;i<len -1;i++) { var idx = Math.floor(M ...

  8. Fisher–Yates shuffle 洗牌算法(zz)

    1,缘起 最近工作上遇到一个问题,即将一组数据,比如[A,B,C,D,E]其中的两个B,E按随机排列,其他的仍在原来的位置: 原始数组:[A,B,C,D,E] 随机字母:[B,D] 可能结果:[A,B ...

  9. 519. Random Flip Matrix(Fisher-Yates洗牌算法)

    1. 问题 给定一个全零矩阵的行和列,实现flip函数随机把一个0变成1并返回索引,实现rest函数将所有数归零. 2. 思路 拒绝采样 (1)先计算矩阵的元素个数(行乘以列),记作n,那么[0, n ...

随机推荐

  1. 豹子安全-注入工具-疑问_MySQL_基于联合查询_按钮【获取基本信息】不能成功的解决方法。

    豹子安全-注入工具-疑问_MySQL_基于联合查询_按钮[获取基本信息]不能成功的解决方法. 网站: http://www.leosec.net 如下GIF影片所示:

  2. Java并发编程(04):线程间通信,等待/通知机制

    本文源码:GitHub·点这里 || GitEE·点这里 一.概念简介 1.线程通信 在操作系统中,线程是个独立的个体,但是在线程执行过程中,如果处理同一个业务逻辑,可能会产生资源争抢,导致并发问题, ...

  3. libevent到底是同步还是异步,是阻塞还是非阻塞

    应该从不同角度看libevent的同步/异步.阻塞/非阻塞: IO数量的角度:select出来之前,会阻塞在一个io上,处理完成后再阻塞在下一个io上:之后就是把所有的io fd拿过来,都不阻塞,一个 ...

  4. 接口testing简介

    一.基础介绍 1.什么是接口 我们常说的接口一般指2种1)API:应用程序编程接口 2)GUI:图形用户界面(接口) 这里我们主要说API——接口测试   2.接口测试的目的 测试接口的正确性和稳定性 ...

  5. 初涉WebGL

    之前一直在捣鼓Vue和React栈,对组件化架构项目有了些理解和体会.今天尝尝WebGL,当然,并不打算现在深入,只是略作了解,我知道这个坑很深. js的图形库.3d库也有好几款比较流行的,如游戏开发 ...

  6. Unity Singleton 单例类(Unity3D开发)

    一.添加单例模板类 using UnityEngine; public class Singleton<T> : MonoBehaviour where T : MonoBehaviour ...

  7. Django之ORM配置与单表操作

    ORM数据库操作流程: 1.    配置数据库(项目同名包中settings.py和__init__.py) 2.    定义类(app包中models.py),执行建表命令(Tools---> ...

  8. ionic + asp.net core webapi + keycloak实现前后端用户认证和自动生成客户端代码

    概述 本文使用ionic/angular开发网页前台,asp.net core webapi开发restful service,使用keycloak保护前台页面和后台服务,并且利用open api自动 ...

  9. Linux内存屏障浅析

    根据该文章整理 https://blog.csdn.net/myxmu/article/details/8035025 1 解决的问题 内存屏障主要解决了单处理器下的乱序问题和多处理器下的内存同步问题 ...

  10. JSONObject转换为map

    http://cloudyxuq.iteye.com/blog/1618213 private static HashMap<String, String> toHashMap(Objec ...