魔术师发牌 Java实现

魔术师发牌问题

 

问题描述:

魔术师利用一副牌中的13张黑牌,预先将他们排好后叠放在一起,牌面朝下。对观众说:“我不看牌,只数数就可以猜到每张牌是什么,我大声数数,你们听,不信?现场演示。”魔术师将最上面的那张牌数为1,把他翻过来正好是黑桃A,将黑桃A放在桌子上,第二次数1,2,将第一张牌放在这些牌的下面,将第二张牌翻过来,正好是黑桃2,也将它放在桌子上这样依次进行将13张牌全部翻出,准确无误。

 

问题:牌的开始顺序是如何安排的?

用循环链表来解决

解题思路:好像是约瑟夫问题的反向求解。先看一下图

《魔术师发牌 Java实现》

下方是已知的最后顺序,且已知循环链表有13个元素,所以建立13个空格代表循环链表,从1开始依次往里填入数,只能数空的空格,有数的空格要跳过,因为数到的牌会被抽走,最后填满如图所示,按照这个思路写代码。

public class MoshushifapaiTest {

	public static void magician(){
		
		Node first = new Node(1);
		first.nextNode = first;
		Node last = first;
		
//		1:先创建一个空的 循环链表,确定一个位置为起始位置,data为1
		for(int i = 2;i<14;i++){
			Node next = new Node();
			next.nextNode = first;
			last.nextNode = next;
			last = next;
		}
		
//		2:从data为1node的下一个node开始数,数两个,依次填入牌的号码,
//		直到数到最大的13次,将13填入循环链表中
		Node now = first;
		for(int i=2;i<14;i++){
			int j = 1;
//			i:应该数的次数,比如填入i时,应该在链表中数i次。
//			j:实际数的次数,比如填入i时,应该数i次,当时当前数到了j次,j<=i
//			当 i=j 时往循环链表中填入 当前数字
			
			
//			从填入的下一个开始数1
			Node next = now.nextNode;
			
			while(true){
				
//				data 为0 说明是空的node,如果不是空的node 要跳过,且不记录数的次数
				if(next.data==0){
					
//					当应该数的次数和实际数的次数相等时,往当前node填入此数,并且now为当前node
					if(j==i){
						next.data = i;
						now = next;
						
//						跳出while
						break;
					}
					j++;
				}
				next = next.nextNode;
			}
			
		}
		
		System.out.println();
		
		while(true){
			now = first;
			boolean flag = true;
			while(true){
				if(now.data!=1){
					System.out.print(now);
					now = now.nextNode;
				}else if(now.data==1&&flag){
					System.out.print(now);
					flag = false;
					now = now.nextNode;
				}else{
					break;
				}
			}
			break;
			
		}
		
		
	}

	public static void main(String[] args) {
		magician();
	}
}

class Node{
	int data;
	Node nextNode;
	
	public Node(int data){
		this.data = data;
	}
	
	public Node(){
		
	}
	
	@Override
	public String toString() {
		return "|黑桃"+data+"|";
	}
}
    原文作者:魔术师发牌问题
    原文地址: https://blog.csdn.net/CmdSmith/article/details/54093347
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞