zoukankan      html  css  js  c++  java
  • 一个翻牌算法

    本周四同事分享了一个思维训练的PPT,里面有一个关于翻牌的题目,题目大致是:拿出从A到10的10张扑克牌,背面朝上摞在一起。首先把最上面的一张挪到下面,掀开新出现的一张牌是A,取出,再挪一张牌到下面,翻一张是2,依次类推,可以有顺序地翻出A到10的牌来。请问这10张牌最初是怎么排列的?看完这个题目,我当时说可以用一个算法实现。

    第二天6点多醒来就一直在想这个问题,开始的时候想用递归实现,最后发现有点复杂,自己实现不了,然后想用数组实现,想法大致是这样的,先将这N个数存到数组中,然后将第一张插到最后面,第二张为A,以此类推,将每张牌经过的索引都记下来,因为每张牌最后是几是知道的,然后反推出1~N张牌是多少,但是发现记录牌经过的索引有点麻烦,效率也不高,记录的数组的第一个元素即为所求。

    早上到了公司一边干活,一边实现这个算法,从题目可以很容易看出奇数位一次为1~N/2,剩下的就是求偶数位的值,马上写了个算法,运行是发现有的结果是正确的,大部分是错的,于是写了个测试方法,测试方法就很简单了,这个方法只用模拟翻牌的过程,然后输出的结果为1~N就是正确的,否则就是错误的。经测试发现我的算法思路完全是错误的,但是通过这个测试算法,我发现了能够正确实现这个题目的方法。这个题目其实不是一个递归的过程,而是一个进栈出栈的过程,奇数位进栈,偶数位出栈。我们知道最后的结果,把每张牌当做一个对象,就是进栈出栈都是以引用的方式,翻牌完成后,按顺序将它们的值一次赋值为1~N,那么我们也就知道开始的牌的顺序了,就这么简单,思路就这么简单,实现起来也就很快,于是马上实现了一个粗糙算法,最后用一个Window Form实现了,发给了同事看看,为了让大家能看得清楚,记录了翻牌的过程,当然要记录过程也是很简单的。

    代码真的很简单,将每张牌当做一个对象,这样就不用记录牌经过的过程,引用类型吗!创建的对象的个数为N,过程也是线性的,不会有性能问题。

    主要代码如下(代码很粗糙,但思路简单清晰,我们知道就是对的),源码下载

     //将牌定义成对象
            public class Card
            { 
                public int Value=0 ;
                public override string ToString()
                {
                    return Value.ToString();
                } 
            }
    
            //测试算法,记录了翻牌过程
            static List<string> TestResult(Card[] arr)
            {
                if (arr == null)
                { 
                   throw new Exception("参数异常");
                }
                int len = arr.Length;
                Queue<Card> queue = new Queue<Card>(len);
                foreach (Card i in arr)
                {
                    queue.Enqueue(i);
                }
                List<string> list = new List<string>(len);
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < len; i++)
                {
                    list.Add(GetItem(sb.ToString(),queue));
                    Card cur = queue.Dequeue();
                    queue.Enqueue(cur);
                    sb.Append(queue.Dequeue().ToString().PadRight(3,' ')+"  ");
                }
                return list;
            }
    
            static string GetItem(string s,Queue<Card> queue)
            { 
                StringBuilder sb = new StringBuilder(s);
                foreach (var item in queue)
                {
                    sb.Append(item.ToString().PadRight(3, ' ') + "  ");
                }
                return sb.ToString();
            }
    
            //实现翻牌的算法
            static Card[] TestArr(int size)
            {
                Card[] arr = new Card[size];
                for (int i = 0; i < size; i++)
                {
                    arr[i] = new Card();
                }
                int len = arr.Length;
                Queue<Card> queue = new Queue<Card>(len);
                foreach (Card i in arr)
                {
                    queue.Enqueue(i);
                }
                for (int i = 1; i <= len; i++)
                {
                    Card cur = queue.Dequeue();
                    queue.Enqueue(cur);
                    cur = queue.Dequeue();
                    cur.Value = i;
                }
                return arr;
            }

    几个截图,如果题目我说得不清楚,下面几张图应该可以让大家看得更明白

  • 相关阅读:
    文本框输入内容提示消失的两种实现
    改变选择网页文字背景色
    软件增加一键处理功能
    全自动相机标定软件
    近景/低空摄影测量系统DPMatrix增加新功能
    DPMatrix软件新增了DEM/DOM制作模块,功能基本齐整!
    DPMatrix软件新增了图像匀光和色彩匹配批处理功能
    基于GPU/CUDA的全景图拼接
    基于GPU\CUDA并行处理技术的摄影测量
    软件与PATB平差数据交换
  • 原文地址:https://www.cnblogs.com/hlxs/p/2687368.html
Copyright © 2011-2022 走看看