• Leetcode 488.祖玛游戏


    祖玛游戏

    回忆一下祖玛游戏。现在桌上有一串球,颜色有红色(R),黄色(Y),蓝色(B),绿色(G),还有白色(W)。 现在你手里也有几个球。

    每一次,你可以从手里的球选一个,然后把这个球插入到一串球中的某个位置上(包括最左端,最右端)。接着,如果有出现三个或者三个以上颜色相同的球相连的话,就把它们移除掉。重复这一步骤直到桌上所有的球都被移除。

    找到插入并可以移除掉桌上所有球所需的最少的球数。如果不能移除桌上所有的球,输出 -1 。

    示例:

    输入: "WRRBBW", "RB"

    输出: -1

    解释: WRRBBW -> WRR[R]BBW -> WBBW -> WBB[B]W -> WW (翻译者标注:手上球已经用完,桌上还剩两个球无法消除,返回-1)

    输入: "WWRRBBWW", "WRBRW"

    输出: 2

    解释: WWRRBBWW -> WWRR[R]BBWW -> WWBBWW -> WWBB[B]WW -> WWWW -> empty

    输入:"G", "GGGGG"

    输出: 2

    解释: G -> G[G] -> GG[G] -> empty

    输入: "RBYYBBRRB", "YRBGB"

    输出: 3

    解释: RBYYBBRRB -> RBYY[Y]BBRRB -> RBBBRRB -> RRRB -> B -> B[B] -> BB[B] -> empty

    标注:

    1. 你可以假设桌上一开始的球中,不会有三个及三个以上颜色相同且连着的球。
    2. 桌上的球不会超过20个,输入的数据中代表这些球的字符串的名字是 "board" 。
    3. 你手中的球不会超过5个,输入的数据中代表这些球的字符串的名字是 "hand"。
    4. 输入的两个字符串均为非空字符串,且只包含字符 'R','Y','B','G','W'。

    思路:

    题目希望我们用最少的球来消掉桌上所有的球,如果不能完全消掉,返回-1。

    我们使用哈希表来统计手中每种球的个数。

    然后我们遍历桌上的球,我们找连续相同球的个数,在没有可以消除的情况下,连续的个数只能是1个或2个,然后我们用3减去连续个数,就是我们需要补充的球数以使其可以被消除,那么我们在哈希表表中看我们手中的该类型的球够不够,如果够就表示可以消除,我们在哈希表中减去需要使用掉的球数,然后将消掉的球移除。

    然后对新的字符串调用递归,如果可以成功消除,会返回一个结果,该结果加上之前需要的球数用来更新结果res,注意调用完递归要恢复哈希表的状态(backtrack)。

    Time Complexity: O(N) Space Complexity: O(N)

     1 class Solution {
     2     int MAXCOUNT = 6;
     3     // the max balls you need will not exceed 6 since "The number of balls in your hand won't exceed 5"
     4     public int findMinStep(String board, String hand) {
     5         int[] handCount = new int[26];
     6         for (int i = 0; i < hand.length(); i++) {
     7             handCount[hand.charAt(i) - 'A']++;
     8         }
     9         int result = backtrack(board + "#", handCount);
    10         // append a "#" to avoid special process while j==board.length, make the code shorter.
    11         return result == MAXCOUNT ? -1 : result;
    12     }
    13 
    14     private int backtrack(String s, int[] h) {
    15         s = removeConsecutive(s);
    16         if (s.equals("#")) return 0;
    17         int rs = MAXCOUNT, need = 0;
    18         int i = 0;
    19         for (int j = 0 ; j < s.length(); ++j) {
    20             if (s.charAt(j) == s.charAt(i)) continue;
    21             need = 3 - (j - i);
    22             //balls need to remove current consecutive balls.
    23             if (h[s.charAt(i) - 'A'] >= need) {
    24                 h[s.charAt(i) - 'A'] -= need;
    25                 rs = Math.min(rs, need + backtrack(s.substring(0, i) + s.substring(j), h));
    26                 h[s.charAt(i) - 'A'] += need;
    27             }
    28             i = j;
    29         }
    30         return rs;
    31     }
    32     //remove consecutive balls longer than 3
    33     private String removeConsecutive(String board) {
    34         int i = 0;
    35         for (int j = 0; j < board.length(); ++j) {
    36             if (board.charAt(j) == board.charAt(i)) continue;
    37             if (j - i >= 3) return removeConsecutive(board.substring(0, i) + board.substring(j));
    38             else i = j;
    39         }
    40         return board;
    41     }
    42 }
  • 相关阅读:
    🍖名称空间与作用域
    🍖文件打开模式 "t"
    🍖函数参数
    【转】LINQ中的Aggregate语法
    【转】c#中string.trimstart() 和string.trimend() 的用法
    1094 和为k的连续区间(暴力)
    1095 Anigram单词
    1031 骨牌覆盖 (斐波拉契数列)
    最长公共子序列(模板 LCSL)
    1092 回文字符串(LCSL_DP)
  • 原文地址:https://www.cnblogs.com/kexinxin/p/10372500.html
Copyright © 2020-2023  润新知