当前位置 博文首页 > Inmaturity_7的博客:算法练习帖--24--Dota2 参议院(Java)

    Inmaturity_7的博客:算法练习帖--24--Dota2 参议院(Java)

    作者:[db:作者] 时间:2021-08-01 11:46

    Dota2 参议院

    一、题目描述

    Dota2 的世界里有两个阵营:Radiant(天辉)和 Dire(夜魇)

    Dota2 参议院由来自两派的参议员组成。现在参议院希望对一个 Dota2 游戏里的改变作出决定。他们以一个基于轮为过程的投票进行。在每一轮中,每一位参议员都可以行使两项权利中的一项:

    • 禁止一名参议员的权利:

    参议员可以让另一位参议员在这一轮和随后的几轮中丧失所有的权利。

    • 宣布胜利:
      如果参议员发现有权利投票的参议员都是同一个阵营的,他可以宣布胜利并决定在游戏中的有关变化

    给定一个字符串代表每个参议员的阵营。字母 “R” 和 “D” 分别代表了 Radiant(天辉)和 Dire(夜魇)。然后,如果有 n 个参议员,给定字符串的大小将是 n。

    以轮为基础的过程从给定顺序的第一个参议员开始到最后一个参议员结束。这一过程将持续到投票结束。所有失去权利的参议员将在过程中被跳过。

    假设每一位参议员都足够聪明,会为自己的政党做出最好的策略,你需要预测哪一方最终会宣布胜利并在 Dota2 游戏中决定改变。输出应该是 Radiant 或 Dire。
    (题目来源:力扣(LeetCode))

    二、解决方法

    1.字符串拼接

    public static String predictPartyVictory(String senate) {
            //记录当前已有的Dire数目
            int dNum=0;
            //记录当前已有的Radiant数目
            int rNum=0;
            //将senate字符串转换为StringBuilder
            StringBuilder senateStr=new StringBuilder(senate);
            for (int i = 0; i < senateStr.length(); i++) {
                //返回条件:当不含Radiant或Dire的时候直接返回
                if(!senateStr.toString().contains("D")) {
                    return "Radiant";
                }
                if(!senateStr.toString().contains("R")) {
                    return "Dire";
                }
                if(senateStr.charAt(i)=='R') {
                    //当现在为R的时候如果dNum等于0,R的数++,并且拼接到字符串后面(如果没被投,就有可能下一轮投票)
                    if(dNum==0) {
                        rNum++;
                        senateStr.append("R");
                    }else {
                        //有d的话,这个R最前,肯定要被投掉
                        dNum--;
                    }
                }else {
                    if(rNum==0) {
                        dNum++;
                        senateStr.append("D");
                    }else {
                        rNum--;
                    }
                }
                //循环后的字符就不再需要了
                senateStr.setCharAt(i, ' ');
            }
            return null;
        }
    
    1. 双队列
    public String predictPartyVictory(String senate) {
                //获取字符串长度
                int n = senate.length();
                //新建两个队列存储字符对应的下标
                Queue<Integer> radiant = new LinkedList<Integer>();
                Queue<Integer> dire = new LinkedList<Integer>();
                for (int i = 0; i < n; ++i) {
                    if (senate.charAt(i) == 'R') {
                        radiant.offer(i);
                    } else {
                        dire.offer(i);
                    }
                }
                //比较两个队列中的下标
                //方式:投最近的,投完加入队列尾,有机会再投或者被投
                while (!radiant.isEmpty() && !dire.isEmpty()) {
                    int radiantIndex = radiant.poll(), direIndex = dire.poll();
                    if (radiantIndex < direIndex) {
                        radiant.offer(radiantIndex + n);
                    } else {
                        dire.offer(direIndex + n);
                    }
                }
                //按radiant队列参考返回
                return !radiant.isEmpty() ? "Radiant" : "Dire";
            }
    
    1. 记录(评论区大佬方法)
     public String predictPartyVictory(String senate) {
            int Rnumber = 0;//R阵营总人数
            int Dnumber = 0;//D阵营总人数
            int curBanR = 0;//当前被ban
            int curBanD = 0;//当前被ban
            int totalBanR = 0;//被ban总数
            int totalBanD = 0;//被ban总数
            char[] chars = senate.toCharArray();
            boolean flag = true;
            while(true){
                for(int i = 0;i < chars.length;i++){
                    char cur = chars[i];
                    if(cur == 'R'){
                        if(flag)
                            Rnumber++;
                        if(curBanR == 0){
                            curBanD++;
                            totalBanD++;
                            if(totalBanD == Dnumber  && !flag)return "Radiant";
                        }else{
                            curBanR--;
                            chars[i] = 'r';
                        }
                    }else if(cur == 'D'){
                        if(flag)
                            Dnumber++;
                        if(curBanD == 0){
                            curBanR++;
                            totalBanR++;
                            if(totalBanR == Rnumber  && !flag)return "Dire";
                        }else{
                            curBanD--;
                            chars[i] = 'd';
                        }
                    }
                }
                flag = false;
                if(totalBanD >= Dnumber)return "Radiant";
                if(totalBanR >= Rnumber)return "Dire";
            }
        }
    
    cs