488. Zuma Game(leetcode DFS hard)

来源:互联网 发布:financial market 知乎 编辑:程序博客网 时间:2024/06/05 20:47

本题采用DFS求解,代码参考来自leetcode discussion, 地址如下
https://discuss.leetcode.com/topic/76681/simple-c-dfs-solution-using-list
不过我进行了相关的改进和说明。


488. Zuma Game题目地址

https://leetcode.com/problems/zuma-game/?tab=Description

题目描述

Think about Zuma Game. You have a row of balls on the table, colored red(R), yellow(Y), blue(B), green(G), and white(W). You also have several balls in your hand.

Each time, you may choose a ball in your hand, and insert it into the row (including the leftmost place and rightmost place). Then, if there is a group of 3 or more balls in the same color touching, remove these balls. Keep doing this until no more balls can be removed.

Find the minimal balls you have to insert to remove all the balls on the table. If you cannot remove all the balls, output -1.

Examples:Input: "WRRBBW", "RB"Output: -1Explanation: WRRBBW -> WRR[R]BBW -> WBBW -> WBB[B]W -> WWInput: "WWRRBBWW", "WRBRW"Output: 2Explanation: WWRRBBWW -> WWRR[R]BBWW -> WWBBWW -> WWBB[B]WW -> WWWW -> emptyInput:"G", "GGGGG"Output: 2Explanation: G -> G[G] -> GG[G] -> empty Input: "RBYYBBRRB", "YRBGB"Output: 3Explanation: RBYYBBRRB -> RBYY[Y]BBRRB -> RBBBRRB -> RRRB -> B -> B[B] -> BB[B] -> empty 

Note:
1. You may assume that the initial row of balls on the table won’t have any 3 or more consecutive balls with the same color.
2. The number of balls on the table won’t exceed 20, and the string represents these balls is called “board” in the input.
3. The number of balls in your hand won’t exceed 5, and the string represents these balls is called “hand” in the input.
4. Both input strings will be non-empty and only contain characters ‘R’,’Y’,’B’,’G’,’W’.

ac思路和注意点

采用dfs,首先需要构造类似如下的结构

RRBBBGYYWWWYB, 转化后的表示为[[“R”, 2], [“B”, 3], [“G”, 1], [“B”, 1]]

可以采用list进行存储(因为需要不断的调整,删除操作很多)

该开始没有封装一个堆list进行清除的函数,写的太乱,没做出来,参考了如下的

https://discuss.leetcode.com/topic/76681/simple-c-dfs-solution-using-list

  • 我的改进1

它写的cleanBoard(list<> &li; 函数是有问题的

比如对于“RBYYYBBRRRBRR”,是可以全部清除的,所以这个清除函数还是需要仔细考虑的(做到瞻前顾后)

  • 我的改进2

对于hand字符串,可以采用map结构存储字符数量,使用一个就+1,回溯对应减操作

  • 注意点
    在dfs时候,需要明白何时进行cleanBoard操作,list是可以直接赋值操作的,对于list<>::iterator需要清清楚的认识 erase,prev,next等操作方法。

我的ac代码如下

这里写图片描述

class Solution {public:    const static int kMaxNeed = 6;    struct data{        char c;        int cnt;        data(char _c = '.', int _cnt = -1)        {            c = _c;            cnt = _cnt;        }    };    void cleanBoard(list<data> &li)    {        list<data>::iterator it = li.begin();        while(it != li.end())        {            if(it == li.begin())            {                if(it->cnt >= 3)                {                    it = li.erase(it);                }else{                    ++it;                }            }else{                if(it->c == std::prev(it)->c){                    it->cnt += std::prev(it)->cnt;                    li.erase(std::prev(it));                    ++it;                }else{                    if(it->cnt >= 3)                    {                        if(std::next(it) != li.end() && it->c != std::next(it)->c )                        {                            it = li.erase(it);                        }else{                            ++it;                        }                    }else{                        if(std::prev(it)->cnt >= 3)                        {                            li.erase(std::prev(it));                        }else{                            ++it;                        }                    }                }            }        }// end while        if((int)li.size() == 0)            return;        it = --li.end();        if(it->cnt >= 3)        {            li.erase(it);        }    }    int dfs(list<data> &li, map<char,int> &mp)    {        cleanBoard(li);        if( (int)li.size() == 0)            return 0;        int minNeed = kMaxNeed;        for (auto it = li.begin(); it != li.end(); ++it) {            int need = 3 - it->cnt;            if(mp.count(it->c) != 0 && mp[it->c] >= need){                mp[it->c] -= need;                if(mp[it->c] == 0){                    mp.erase(it->c);                }                it->cnt += need;                list<data> liNext = li;                int ret = dfs(liNext, mp); //递归 , 回溯                // li 需要need数目 编程 liNext, 而liNext变成最短需要ret数目                // 那么 ret + need 就是当前的li,mp组合 变成最短需要的个数了                minNeed = min(minNeed , ret + need);                mp[it->c] += need;                it->cnt -= need;            }        }        return minNeed;    }    int findMinStep(string board, string hand) {        list<data> li;        string tmp = board + ".";        int cnt = 0;        int tmpLen = tmp.size();        int lastChar = '.';        for(int i=0;i<tmpLen;i++){            if(tmp[i] != lastChar)            {                if(cnt != 0)                {                    data dt;                    dt.c = lastChar;                    dt.cnt = cnt;                    li.push_back(dt);                }                lastChar = tmp[i];                cnt = 1;            }else{                cnt ++;            }        }        cleanBoard(li);        map<char,int> mp;        string::iterator it = hand.begin();        while(it != hand.end())        {            mp[*it] += 1;            ++it;        }        int ret = dfs(li,mp);        return ret == kMaxNeed ? -1 : ret;    }};
0 0
原创粉丝点击