zoukankan      html  css  js  c++  java
  • 小朋友排顺序

    一个热爱技术的菜鸟...用点滴的积累铸就明日的达人
    CSDN博客链接: http://blog.csdn.net/my_confesser 
      
    今天在网上看到一道编程测验题,感觉挺有意思的,于是顺手写了写。记录下来与大家一起交流交流,如果有更好的办法,请告知,一起学习
     
    题目
      幼儿园老师要带小朋友们出去玩,要求小朋友们自己排好队伍(比如这样"GGGBBG"),但是老师发现如果男孩子旁边有个小女孩的话,男孩子会欺负小女孩,所以老师想达到这样的一种效果:男孩子都在一起,女孩子也都在一起(比如这样"BBGGGG"或者"GGGGBB"),每次交换小朋友位置的时候只能将小朋友和旁边的小朋友交换(也就是不能这样换"GGGBBG"-->"GGGGBB",只能这样"GGGGBBG"-->"GGGGBGB"-->"GGGGGBB")。最后老师想知道如果随意给出一个小朋友的顺序(因为小朋友排队都比较随意),那么将小朋友排号顺序至少要多少次交换。
    例如:
      一开始队伍的顺序是:GGGGBBG
      那么期望顺序有两种:GGGGGBB与BBGGGGG
      对于第一种:GGGGBBG-->GGGGBGB-->GGGGGBB
      对于第二种:GGGGBBG-->GGGBGBG-->GGBGGBG-->GBGGGBG-->BGGGGBG-->BGGGBGG-->BGGBGGG-->BGBGGGG-->BBGGGGG
      很明显第一种只需要两步,第二种需要八步,那么最佳答案是2
     
    思路
      首先大家要注意一下,题目的意图是让我们求出最佳交换次数,而不是交换顺序(我一开始就在顺序上纠结了好久...写了好长的一段代码)。
    那么现在考虑了,其实每种队列都有两种最佳情况,一种是B在G前面,一种是G在B前面。不妨把每种的情况都计算一次,之后比较两个次数的大小就可以得出最佳答案了。
        public int getMinFrequency(char[] queue) {
            int gFrequency = getMinGBF(queue);//G在B前面的最佳次数
            int bFrequency = getMinBGF(queue);//B在G前面的最佳次数
            return gFrequency < bFrequency ? gFrequency : bFrequency;
        }
     先以G在前B在后去考虑问题,那么现在的问题已经被细化成了G在B前时需要几次能交换完成(有人会问这有细化问题吗?我的理解:其实我们无论遇到什么问题,能化成子问题的先化成子问题,即使这个子问题只是迈出了一个很小的步子,那也是进步,例如本题中,一开始可能要考虑到底是G在B前面,还是B在G前面呢?而此时,我们已经避免了这个问题...这已经有很大进步了)。对于GGGGBBG要转换成GGGGGBB,其实只需要考虑每个G前面有多少个B就可以了,因为我们总是假设左边已经是排好序了,然后判断下一个如何交换到排好序的队列里面(其实这里面的思想就是我们熟悉的插入排序的思想,因为前面排好序的队列始终都是G在B前面的,下一个元素只需要交换B的数量的交换即可交换到指定位置)。因此只需要从队列开始的位置扫描一下每个G前面有多少个B,之后将所有的G前面的B的数目相加就得到次数了。
        private int getMinGBF(char[] queue) {
            int count = 0;
            int sum = 0;
            for (char gb : queue) {
                if (gb == 'B') {
                    count++;
                } else {
                    sum += count;
                }
            }
            return sum;
        }
    

      最后我们再考虑一下,我们的程序在极端情况下有没有问题(例如:GGG,BBB,空  这几种情况),很幸运,经过推理都没有问题~~

    程序

    public class Main {
    
        public int getMinFrequency(char[] queue) {
            int gFrequency = getMinF(queue, 'G');//G在B前面的最佳次数
            int bFrequency = getMinF(queue, 'B');//B在G前面的最佳次数
            return gFrequency < bFrequency ? gFrequency : bFrequency;
        }
    
        /**
         * @param firstChar 最终队列中第一个char,如果是G的话,那么意味G在B前,反之亦然
         */
        private int getMinF(char[] queue, char firstChar) {
            int count = 0;
            int sum = 0;
            for (char gb : queue) {
                if (gb == firstChar) {
                    count++;
                } else {
                    sum += count;
                }
            }
            return sum;
        }
    }
    

      

  • 相关阅读:
    一图看懂host_only nat bridge拓扑结构
    Linux iptables原理--数据包流向
    linux iptables常用命令之配置生产环境iptables及优化
    linux service命令解析
    mysql 二进制日志后缀数字最大为多少
    mysql基于init-connect+binlog完成审计功能
    MySQL5.7(5.6)GTID环境下恢复从库思(qi)路(yin)方(ji)法(qiao)
    Centos6.5 python升级成2.7版本出现的一些问题解决方法
    python生成随机密码
    (原创)c++中的类型擦除
  • 原文地址:https://www.cnblogs.com/sachen/p/6617755.html
Copyright © 2011-2022 走看看