问题描述: 手上有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); } } } }