Day7: GG高频面经 | LC843猜猜这个单词 | 随机选择,调用API|Sundri

843. 猜猜这个单词

难度困难123

给你一个由 不同 字符串组成的单词列表 words ,其中 words[i] 长度均为 6words 中的一个单词将被选作秘密单词 secret

另给你一个辅助对象 Master ,你可以调用 Master.guess(word) 来猜单词,其中参数 word 长度为 6 且必须是 words 中的字符串。

Master.guess(word) 将会返回如下结果:

  • 如果 word 不是 words 中的字符串,返回 -1 ,或者

  • 一个整数,表示你所猜测的单词 word 与 秘密单词 secret 的准确匹配(值和位置同时匹配)的数目。

每组测试用例都会包含一个参数 allowedGuesses ,其中 allowedGuesses 是你可以调用 Master.guess(word) 的最大次数。

对于每组测试用例,在不超过允许猜测的次数的前提下,你应该调用 Master.guess 来猜出秘密单词。最终,你将会得到以下结果:

  • 如果你调用 Master.guess 的次数大于 allowedGuesses 所限定的次数或者你没有用 Master.guess 猜到秘密单词,则得到 "Either you took too many guesses, or you did not find the secret word." 。

  • 如果你调用 Master.guess 猜到秘密单词,且调用 Master.guess 的次数小于或等于 allowedGuesses ,则得到 "You guessed the secret word correctly." 。

生成的测试用例保证你可以利用某种合理的策略(而不是暴力)猜到秘密单词。

示例 1:

输入:secret = "acckzz", words = ["acckzz","ccbazz","eiowzz","abcczz"], allowedGuesses = 10

输出:You guessed the secret word correctly.

解释:

master.guess("aaaaaa") 返回 -1 ,因为 "aaaaaa" 不在 words 中。

master.guess("acckzz") 返回 6 ,因为 "acckzz" 是秘密单词 secret ,共有 6 个字母匹配。

master.guess("ccbazz") 返回 3 ,因为 "ccbazz" 共有 3 个字母匹配。

master.guess("eiowzz") 返回 2 ,因为 "eiowzz" 共有 2 个字母匹配。

master.guess("abcczz") 返回 4 ,因为 "abcczz" 共有 4 个字母匹配。

一共调用 5 次 master.guess ,其中一个为秘密单词,所以通过测试用例。

示例 2:

输入:secret = "hamada", words = ["hamada","khaled"], allowedGuesses = 10

输出:You guessed the secret word correctly.

解释:共有 2 个单词,且其中一个为秘密单词,可以通过测试用例。

提示:

  • 1 <= words.length <= 100

  • words[i].length == 6

  • words[i] 仅由小写英文字母组成

  • words 中所有字符串 互不相同

  • secret 存在于 words 中

  • 10 <= allowedGuesses <= 30

#解题思路

一开始看到这个题目,我连题目想要做什么都没看懂。后面看了youtube视频才知道,题目想要我们设计一个算法, 让我们能够尽可能把调用master.guess api的次数控制在 10次以内。主要解题思路如下:
secret = "acckzz", words = ["acckzz","ccbazz","eiowzz","abcczz"], allowedGuesses = 10
先从words里面随机选择一个单词:使用random产生一个在[0,len(words)-1] 之间的index,选出这个单词,例如: abcczz
调用guess API,返回一个当前匹配的次数。master.guess("abcczz") 函数会返回 4
创建一个candidates数组;以 abcczz 为基准,遍历words里面的其他单词,寻找匹配值 >= 4 的单词,加入到candidates
第一次遍历之后,candidates数组长这样:["acckzz"]
让candidates数组等于words,重新随机选取一个单词,重复1,2,3,4,5的步骤,直到candidates数组为空,或者调用guess API的返回值 == 6 (len(secret)

#原创代码

class Solution(object):
    import random
    def findSecretWord(self, words, master):
        # 1.随便从word list里面挑选一个单词 w
        # 2. 呼叫guess word,看这个单词和 secret word有几个匹配的,例如返回2
        # 3. 用这个单词 w 和 word list里面所有的单词进行匹配,如果发现 >=2 个匹配的,放进candidate list
        # 4. 再随便从candidate list里面挑选一个单词,和secret word进行匹配,重复上述步骤

        n = len(words)
        if n == 0: return
        index = random.randint(0,n-1)
        first_guess = words[index] 
        matching_num = master.guess(first_guess)
        if matching_num == len(words): return
        
        candidates = []
        def compareWord(word1, word2): # compare word 部分的逻辑代码可以进一步优化
            i,j = 0,0
            count = 0
            while i < len(word1) and j < len(word2):
                if word1[i] == word2[j]:
                    count += 1
                i += 1
                j += 1
            return count 

        for word in words:
            if word == first_guess:
                continue
            if word != first_guess:
                if compareWord(word, first_guess) >= matching_num:
                    candidates.append(word)
        
        self.findSecretWord(candidates, master) # 递归调用的写法可以优化

# 报错:
# empty range for randrange() (0,0, 0) and ValueError("empty range for randrange() (%d,%d, %d)" % (istart, istop, width)) -- 因为candidates在最后的时候会变为空,所以在新一轮调用之前,要对candidates的状态进行判断,如果数组已经是空,说明已经找到了这个单词,函数直接return即可

#优化代码:

  1. 不一定得递归调用,可以通过while循环,让words = candidates 数组的方式不断更新words数组

  1. compareword的写法:不一定使用双指针,可以使用python里面的zip方法,一个一个单词去比较

class Solution:
    import random
    def findSecretWord(self, words, master):
        times = 0
        match_num = 0
        while times < 10 and match_num != 6:
            n = len(words)
            index = random.randint(0,n-1)
            guess_word = words[index]
            match_num = master.guess(guess_word)
            candidates = []
            for word in words:
                if word != guess_word:
                    if self.compareWord(guess_word, word) == match_num:
                        candidates.append(word)
            words = candidates

    def compareWord(self,word1, word2): # rtype: int
        count = 0
        for x,y in zip(word1,word2):
            if x == y:
                count += 1
        return count

#时空复杂度:

# Time: O(10*N) go through each word

# Space: O(10*N) - candidates array

# 时间复杂度:O(10n) = O(n),因为 for 循环运行 10 次或更少,并且在每次迭代中,我们遍历词表,

# 空间复杂度:O(10n) = O(n)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值