299.猜数字游戏

https://leetcode-cn.com/problems/bulls-and-cows/

一、

用一个map,key为数字,value为该数出现的下标集合。首先将secret的映射关系记录,然后拿guess来比较。 由于数字和位置都对的(以下简称A)和数字对位置不对的(简称B)在一次遍历中无法区分(都用key是否存在于map中判断) 因此先一次遍历检测A,并将位置记录。遇到A就将对应set中的下标移除 下一次遍历检测B,注意跳过上一次记录的位置。由于B类的下标不唯一,因此只要检测到key对应的set非空,就弹出一个set元素(此处转化为list执行)。最后注意移除set后检测,若set为空,将对应key也删除

class Solution:
    def getHint(self, secret: str, guess: str) -> str:
        map = {}
        n =len(secret)
        for i in range(n):
            num = secret[i]
            if num not in map:
                map[num] = set([i])
            else:
                map[num].add(i)

        A,B = 0,0
        set_A = set()	#记录A数位置
        # 扫描guess,第一遍先找数字和位置都对的
        for i in range(n):
            num = guess[i]
            if num in map:
                if i in map[num]:
                    A += 1  #累计A数量
                    set_A.add(i)    #标记A数的位置,下次跳过
                    map[num].remove(i)
                    if len(map[num]) == 0:  #set为空就应从map移除
                        del map[num]
        # 第二遍找数字对位置不对的
        for i in range(n):
            if i in set_A:
                continue
            num = guess[i]
            #检测到在map中,B累加1,并将对应set转list,随意弹出一个
            if num in map:	
                B += 1
                map[num] = list(map[num])
                map[num].pop()
                if len(map[num]) == 0:  #list为空就应从map移除
                    del map[num]
        return str(A) + "A" + str(B) + "B"

二、

两个指针s、g同时遍历secret和guess,s==g说明数字和位置都对,A加一。否则s、g处数字出现的次数加一,用cntS[i]cntG[i]记录数字i在sceret和guess中出现的次数(位置匹配除外)。

之后再用两个指针s、g遍历cntS和cntG,数字对而位置不对的个数为s、g较小值。累加得B

class Solution:
    def getHint(self, secret: str, guess: str) -> str:
        A = 0
        cntS, cntG = [0] * 10, [0] * 10
        for s, g in zip(secret, guess):
            if s == g:
                A += 1
            else:
                cntS[int(s)] += 1
                cntG[int(g)] += 1
        B = 0
        for s, g in zip(cntS, cntG):
            B += min(s, g)
        return str(A) + "A" + str(B) + "B"

最后更新于