问题描述:
手上有13张牌,从上往下依次做如下操作:
第1张牌放桌上,第2张挪到手牌的最下面,第3张叠在桌上,第4张挪到手牌的最下面...
一直重复上述过程,直至手上所有的牌都叠在桌上。
叠在桌上的牌,从下往上的次序依次是1、2、3...13
要求-还原操作之前,手牌的次序。
算法分析:
手上的牌,从上到下的次序,
依次编号A1、A2、A3...A13,
挪到桌上之后的次序:
A8、A12、A4、A10、A6、A2、A13、A11、A9、A7、A5、A3、A1
经过分析-
挪放前的手牌,
不能被2^1整除的编号,在桌上的最下方,编号从下到上依次递增...
然后是不能被2^2整除的编号,在桌上的次最下方,编号从下到上依次递增...
然后是不能被2^3整除的编号,在桌上的次次最下方,编号从下到上依次递增...
...
然后是不能被2^countMaxTimes整除的编号,在最上方,编号从下到上依次递增。
JAVA代码编码实现:
package algorithm.poker;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.testng.annotations.Test;
/**
* @date 2018年5月8日
*/
public class ReSortPorker {
private int []targetArray;
public ReSortPorker(int[]targetArray) {
this.targetArray = targetArray;
}
public static Map<Integer, List<Integer>> getResortResult(int[]targetArray){
ReSortPorker reSortPorker = new ReSortPorker(targetArray);
return reSortPorker.getResortResult();
}
private Map<Integer, List<Integer>> getResortResult(){
int maxCount=countMaxTimes(1, 2, this.targetArray.length);
Map<Integer, List<Integer>> map = new TreeMap<Integer, List<Integer>>();
/**
* 每个下标index从2^1 ~ 2^countMaxTimes都遍历一遍,
* 碰到不能整除的2^x 则map.get(2^x).add(index),同时停止遍历
*/
for(int index=0;index<targetArray.length;index++) {
for(int i=1;i<=maxCount;i++) {
if (dowithMap(index, get2n(i), map)) {
break;
}
}
}
return map;
}
/**
* @param index 遍历0~targetArray.length-1
* @param base
* @param map
*
* 如果(index+1)%(2^base)!=0
* @return false && map.get(base).add(index);
*/
private boolean dowithMap(int index,int base,Map<Integer, List<Integer>>map) {
if ((index+1)%base==0) {
return false;
}
if (map.get(base)==null) {
List<Integer> _baseList = new ArrayList<Integer>();
_baseList.add(index);
map.put(base, _baseList);
}else {
map.get(base).add(index);
}
return true;
}
/**
* @param n
* @return 2^n
*/
private int get2n(int n) {
if (n==0) {
return 1;
}else {
return 2*get2n(n-1);
}
}
/**
* @param times
* @param intValue
* @param target
*
* 如果数组元素的个数2^(n-1)<targetArray.length<2^n
* @return n
*/
private int countMaxTimes(int times,int intValue,int target) {
if (times<=0) {
return -1;
}
if (intValue>target) {
return times;
}
if (2*intValue>target) {
return times+1;
}else {
return countMaxTimes(times+1, 2*intValue, target);
}
}
@Test
public static void f() {
Map<Integer, List<Integer>>map = ReSortPorker.getResortResult(new int [] {1,2,3,4,5,6,7,8,9,10,11,12,13});
for(int key:map.keySet()) {
for(int i=0;i<map.get(key).size();i++) {
System.err.println(map.get(key).get(i)+1);
}
}
}
}