取牌魔术

题目描述:

一副从1到n的牌,每次从牌堆顶取一张放桌子上,再取一张放牌堆底,直到手上没牌,最后桌子上的牌是从1到n有序(从下到上),设计程序,输入n,输出牌堆的顺序数组。

解题思路:

以n=5为例:

如果考虑的是最后桌子上的牌是1,2,3,4,5(从上往下)

也就是说,原先的一张牌,先取出5,然后放入牌底一张;再取出4;然后放入牌底一张;再取出3;然后放入牌底一张;再取出2;然后放入牌底一张;再取出1。使用图示表示为(左边褐色箭头所示):则反演可以得到5 1 4 2 3的初始顺序。

《取牌魔术》

同时,也应该注意到,将5取走后,然后放入牌底一张;就得到的是如图所示的n=4的过程。

《取牌魔术》

所以在过程中我们可以想象,对于我们所预设的最后桌子上的牌是1,2,…,n(从上往下),即取牌顺序为n,n-1,…,2,1

对于任意一个n,n必然在第一张,取走之后,在放入一张在牌堆底部;剩下的牌堆必须抽出n-1,…,2,1,即对于n-1时的情况。

所以求n的情况时,先求出n-1时的情况,他的底部的一张是由n的情况的第二张放去的;所以将n-1的情况的底部放回首部,在在首部放上n就是n的情况的解答。

所以伪代码可以表示为:

solution(n)
  list <- solution(n-1)
  list.head <- list.tail
  delete list.tail
  list.head <- n
  return list

 同时,由于题目要求的是最后桌子上的牌是从1到n有序(从下到上),所以只要在输出的时候将i转为n+1-i输出即可。

代码实现

import java.util.LinkedList;
import java.util.Scanner;
public class Main{

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
    	long n = in.nextLong();
    	LinkedList<Long> list = soluation(n);
    	for (Long long1 : list) {
			System.out.print(n+1-long1+" ");
		}
    	System.out.println();
    	in.close();
	}

	private static LinkedList<Long> soluation(long n) {
		if(n==1) {
			LinkedList<Long> list = new LinkedList<Long>();
			list.add((long) 1);
			return list;
		}
		LinkedList<Long> list = soluation(n-1);
		list.addFirst(list.removeLast());
		list.addFirst(n);
		return list;
	}

}

 

    原文作者:魔术师发牌问题
    原文地址: https://blog.csdn.net/alixia111/article/details/82790873
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞