leetcode题解-299. Bulls and Cows

题目: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.
示例:
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.

本题其实比较简单,为了获得所谓提示hint,就是获取bull和cow的个数。bull很容易得到,一个for循环,对应位置字符相等则为bull,计数加一即可。而cow则是除去bull之外两个字符串中相同元素的个数(不考虑位置信息)。
一开始写下了如下代码,当时考虑分别记录secret和guess两个数组数字和其出现次数,所以使用了hashmap来存。由于hashMap在这里相对而言比较耗时,性价比不高,所以只击败了14%的用户。代码入下:

    public static String getHint(String secret, String guess) {
        int bull = 0, cow = 0;
        HashMap<Character, Integer> bulls = new HashMap<>();
        HashMap<Character, Integer> cows = new HashMap<>();
        for(int i=0; i<secret.length(); i++){
            if(secret.charAt(i) == guess.charAt(i))
                bull += 1;
            else{
                if(bulls.containsKey(secret.charAt(i)))
                    bulls.put(secret.charAt(i), bulls.get(secret.charAt(i))+1);
                else
                    bulls.put(secret.charAt(i), 1);
                if(cows.containsKey(guess.charAt(i)))
                    cows.put(guess.charAt(i), cows.get(guess.charAt(i))+1);
                else
                    cows.put(guess.charAt(i), 1);
            }
        }
        for(Character key : bulls.keySet()){
            if(cows.containsKey(key)){
                if(bulls.get(key) > cows.get(key))
                    cow += cows.get(key);
                else cow += bulls.get(key);
            }
        }
        return bull + "A" + cow + "B";
    }

看到代码执行效率如此低下,想想该怎么改进呢?于是便想到数字信息可以使用数组的索引来表示,这样就省去了hashMap这样复杂的数据结构,使得程序匀速速度得以提升,击败了44%的用户。代码入下:

    public static String getHint1(String secret, String guess) {
        int bull = 0, cow = 0;
        int [] bulls = new int [10];
        int [] cows = new int [10];
        for(int i=0; i<secret.length(); i++){
            if(secret.charAt(i) == guess.charAt(i))
                bull += 1;
            else{
                bulls[secret.charAt(i) - 48] ++;
                cows[guess.charAt(i) - 48] ++;
            }
        }
        for(int i=0; i<10; i++){
            if(bulls[i]!=0){
                if(bulls[i] > cows[i])
                    cow += cows[i];
                else cow += bulls[i];
            }
        }
        return bull + "A" + cow + "B";
    }

所以呢,看看还有没有提升的空间,由于上面的代码都是使用了两个数组来保存secret和guess的信息,然后在程序最后使用一个循环来遍历得到cow个数,这其实忽略了其二者的关系,我们可以只使用一个数组来保村0-9这10个数字出现的次数,secret每出现一次便加一,guess每出现一次便减一。而且当其发生正负关系变化的时候cow才加一。这样效率就有提升了一些。这里有两段代码,前面一段54%,后面一段73%。其实代码思想完全相同,不过在中间使用变量的方式不同。所以这提醒我们提高代码效率时不仅仅可以从算法上考虑还可以从编程习惯和程序规范上下手。

    public String getHint2(String secret, String guess) {
        int bull = 0;
        int cow = 0;
        int[] numbers = new int[10];
        for (int i = 0; i<secret.length(); i++) {
            if (secret.charAt(i) == guess.charAt(i)) bull++;
            else {
                if (numbers[secret.charAt(i)-'0']++ < 0) cow++;
                if (numbers[guess.charAt(i)-'0']-- > 0) cow++;
            }
        }
        return bull + "A" + cow + "B";
    }
    public String getHint3(String secret, String guess) {
        int s, g, size = secret.length();
        int bulls = 0, cows = 0;
        int [] nums = new int [10];
        for (int i = 0; i < size; i++) {
            s = secret.charAt(i) - '0';
            g = guess.charAt(i) - '0';
            if (s == g)
                bulls ++;
            else{
                if (nums[s] < 0)
                    cows++;
                nums[s]++;
                if (nums[g] > 0)
                    cows++;
                nums[g]--;
            }
        }
        return bulls + "A" + cows + "B";
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值