299. Bulls and Cows

来源:互联网 发布:深夜解莫软件 编辑:程序博客网 时间:2024/06/07 05:24

You are playing the following Bulls and Cows game with your friend: You write down a number and ask your friend to guess what the number is. Each time your friend makes a guess, you provide a hint that indicates how many digits in said guess match your secret number exactly in both digit and position (called “bulls”) and how many digits match the secret number but locate in the wrong position (called “cows”). Your friend will use successive guesses and hints to eventually derive the secret number.

For example:

Secret number: “1807”
Friend’s guess: “7810”
Hint: 1 bull and 3 cows. (The bull is 8, the cows are 0, 1 and 7.)
Write a function to return a hint according to the secret number and friend’s guess, use A to indicate the bulls and B to indicate the cows. In the above example, your function should return “1A3B”.

Please note that both secret number and friend’s guess may contain duplicate digits, for example:

Secret number: “1123”
Friend’s guess: “0111”
In this case, the 1st 1 in friend’s guess is a bull, the 2nd or 3rd 1 is a cow, and your function should return “1A1B”.
You may assume that the secret number and your friend’s guess only contain digits, and their lengths are always equal.

s思路:
1. 看起来好像没什么难度。用hash没的说,由于有重复的,因此需要对出现的数字的个数计数。
2. 做的过程中,还是很繁琐。
3. 然后看到这个方法,https://discuss.leetcode.com/topic/28445/c-4ms-straight-forward-solution-two-pass-o-n-time 眼前一亮啊!
4. 不用hash,而用两个数组来统计0-9每个数字在两个string中出现的次数。例如:一个string中0出现4次,而另一个中0出现2次,那么很显然cows就出现了2次,把0~9这10个位置中每次最小值加起来就是cows。是不是很棒!
5. 你看,思考角度不同,方法出奇的简单好理解,关键不会写除很多bug的代码。想到之前说过的话:没有繁琐的问题,只有繁琐的方法;有繁琐的方法,说明背后或某个角度能看到简洁的方法!
6. 这个方法确实忽略了,应该在做的时候,就可以想到,因为都是去match数字,而数字就只有10种可能,所以用vector比用hash快;同时,不用一个一个去比较,这样太关注细节的话,容易搞晕,代码调试也比较痛苦,而方法2则是同top的系统角度看问题,不一步一步的细扣每一步的变化,看整体结果即可!
7. 这道题的启发:有的题,看一眼很容易就往细节去了,原因是自己对这块的细节很熟悉,反而不容易站在一个high level看问题,如果不用细节思考结果会更快得到吗?还有一类题,就是很不容易往细节靠,比如之前bit操作题,很难看到以bit为单位的操作,原因也是对int的熟悉程度远远大于对bit的熟悉。因此,多练习多总结,视野和思维更广,等思维更广了以后,还要能遇到熟悉的方法的时候,问问自己是否被一种思路,尤其是被稍微熟悉的思路给绑架了呢?让过去的记忆和由于熟悉而一拥而上的成就感给占据了思维,从而导致不能自然的专注在当下的问题呢?所以,最好的方式是,看到题目思考问题的时候,能从两个角度看问题,balance thinking最好了:即能从top-down的系统的数学的俯瞰式的思维方式,专注简洁和直接的方式;又可以bottom-up的从元问题入手采用步步为营、把问题分解、分离剖析消融成基本问题,然后采用迭代递归或dp或tp或bt等实现呢。最后,再比较那一种实现起来最容易,或代码最简洁,或最锻炼思维等。同时用两个方向入手思考,是因为两个方法都很重要,没有谁比谁好,都只是看问题的角度,位置和立场,而立场决定了自己能看到什么,不是自己眼睛和脑袋好使,确实是自己站的位置让自己真真实实看到了能看到的一切,然后在试图记录整个看到的世界!
8. 追求的真实,就这么简单!

//方法1:双hash,不推荐!class Solution {public:    string getHint(string secret, string guess) {        //        unordered_map<char,int> mm1,mm2;        int n=secret.size();        int bulls=0,cows=0;        for(int i=0;i<n;i++){            if(secret[i]==guess[i]){                bulls++;                }else{                if(mm1.count(guess[i])){                    if(--mm1[guess[i]]==0)                        mm1.erase(guess[i]);                    cows++;                 }else{                    mm2[guess[i]]++;                }                   if(mm2.count(secret[i])){                    if(--mm2[secret[i]]==0)                        mm2.erase(secret[i]);                    cows++;                 }else{                    mm1[secret[i]]++;                }               }            }        return to_string(bulls)+'A'+to_string(cows)+'B';    }};//方法2:不用hash.添加删除神马的太繁琐,直接统计0~9的个数,取最小值!class Solution {public:    string getHint(string secret, string guess) {        //        vector<int> num1(10,0),num2(10,0);        int n=secret.size(),m=guess.size();        if(n!=m) return "0A0B";        int bulls=0,cows=0;        for(int i=0;i<n;i++){            if(secret[i]==guess[i]){                bulls++;                }else{                num1[secret[i]-'0']++;                num2[guess[i]-'0']++;                               }            }        for(int i=0;i<=9;i++){            cows+=min(num1[i],num2[i]);            }        return to_string(bulls)+'A'+to_string(cows)+'B';    }};
0 0