LeetCode 每日一题 2021/11/8-2021/11/14

记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步


目录

      • 11/8 299. 猜数字游戏
      • 11/9 488. 祖玛游戏
      • 11/10 495. 提莫攻击
      • 11/11 629. K个逆序对数组
      • 11/12 375. 猜数字大小 II
      • 11/13 520. 检测大写字母
      • 11/14 677. 键值映射


11/8 299. 猜数字游戏

逐位比较
如果相同则公牛数+1
如果不同 则在两个map中分别记录字符出现次数
奶牛数即为每个字符在两个map中的较小值

def getHint(secret, guess):
    """
    :type secret: str
    :type guess: str
    :rtype: str
    """
    from collections import defaultdict
    n=len(secret)
    smap = defaultdict(int)
    gmap = defaultdict(int)
    bulls = 0
    for i in range(n):
        if secret[i]==guess[i]:
            bulls+=1
        else:
            smap[secret[i]] +=1
            gmap[guess[i]] +=1      
    cows = sum([min(smap[str(i)],gmap[str(i)]) for i in range(10)])
    ans = "{}A{}B".format(bulls,cows)
    return ans    

11/9 488. 祖玛游戏

函数clean用来做消球操作
手球hand 排个序
visited记录(board,hand)状态 防止重复考虑
BFS li存储当前考虑序列[board,hand,放置手球次数]
i,j代表在board[i]前放置第j个手球hand[j]
如果手球与上一次手球一样 则跳过 hand[j]==hand[j-1]
如果手球与上一个位置一样 也跳过放置的情况是一样的 hand[j]==board[i-1]

def findMinStep(board, hand):
    """
    :type board: str
    :type hand: str
    :rtype: int
    """
    def clean(s):
        loc = 0
        while loc<len(s):
            num = 1
            tmp = loc
            while loc<len(s):
                tmp+=1
                if tmp==len(s):
                    break
                if s[loc]==s[tmp]:
                    num+=1
                else:
                    break
            if num>2:
                s = s[:loc]+s[tmp:]
                loc = max(0,loc-1)
                while loc>0:
                    if s[loc]==s[loc-1]:
                        loc = loc-1
                    else:
                        break
            else:
                loc+=1
        return s
    
    
    hand = "".join(sorted(hand))
    li = [(board,hand,0)]
    visited = set([(board,hand)])
    while li:
        curb,curh,step = li[0]
        li = li[1:]
        for i in range(len(curb)+1):
            for j in range(len(curh)):
                ## 如果手中球和上一个颜色一样
                if j>0 and curh[j]==curh[j-1]:
                    continue
                ##上一个位子的球与当前手中球颜色一样
                if i>0 and curb[i-1]==curh[j]:
                    continue
                
                nb = clean(curb[:i]+curh[j]+curb[i:])
                nh = curh[:j]+curh[j+1:]
                if not nb:
                    return step+1
                if (nb,nh) not in visited:
                    li.append((nb,nh,step+1))
                    visited.add((nb,nh))
    return -1    

11/10 495. 提莫攻击

记录中毒结束时间finish

def findPoisonedDuration(timeSeries, duration):
    """
    :type timeSeries: List[int]
    :type duration: int
    :rtype: int
    """
    ans = 0
    finish = -1
    for t in timeSeries:
        if t>finish:
            ans +=duration
        else:
            ans += duration - (finish-t+1)
        finish = t+duration-1
    return ans    

11/11 629. K个逆序对数组

有n个数字[1,n] 产生k个逆序对
dp[n][k]代表n个数字产生k个逆序对情况
考虑最大值n的位置
如果n放在第一位 会产生n-1个逆序对 剩下n-1个数需要产生k-(n-1)个逆序对
如果n放在第二位 会产生n-2个逆序对 剩下n-1个数需要产生k-(n-2)个逆序对
dp[n][k] = dp[n-1][k] + dp[n-1][k-1] + … + dp[n-1][k-(n-1)]
对于dp[n][k-1] = dp[n-1][k-1]+…+dp[n-1][k-(n-1)]+dp[n-1][k-1-(n-1)]
两式错位相减
dp[n][k]-dp[n][k-1] = dp[n-1][k]-dp[n-1][k-n] (k>=n)
=> dp[n][k] = dp[n][k]+dp[n-1][k] - dp[n-1][k-n](if k>=n)
只与n,n-1相关 可以压缩为一维数组

def kInversePairs(n, k):
    """
    :type n: int
    :type k: int
    :rtype: int
    """
    MOD = 10**9+7
    dp = [1]+[0]*k
    for i in range(2,n+1):
        nextdp = [1]+[0]*k
        for j in range(1,k+1):
            nextdp[j] = (nextdp[j-1]+dp[j]-(dp[j-i] if j>=i else 0))%MOD
        dp = nextdp
    return dp[-1]  

11/12 375. 猜数字大小 II

1.dp[i][j]代表在[i,j]范围内最少金额
i>=j时 dp[i][j]=0
对于在[i,j]中遍历每一种可能性k dp[i][j] = min(k+max(dp[i][k-1],dp[k+1][j]))
2.遍历每一种[i,j]长度

def getMoneyAmount1(n):
    """
    :type n: int
    :rtype: int
    """
    dp = [[0]*(n+1) for _ in range(n+1)]
    for i in range(n-1,0,-1):
        for j in range(i+1,n+1):
            dp[i][j] = i+dp[i+1][j]
            for k in range(i,j):
                dp[i][j] = min(k+max(dp[i][k-1],dp[k+1][j]),dp[i][j])
    return dp[1][n]

def getMoneyAmount(n):
    """
    :type n: int
    :rtype: int
    """
    dp = [[0]*(n+2) for _ in range(n+2)]
    for l in range(2,n+1):
        for i in range(1,n-l+2):
            j = i+l-1
            dp[i][j]=float('inf')
            for k in range(i,j+1):
                cur = max(dp[i][k-1],dp[k+1][j])+k
                dp[i][j] = min(dp[i][j],cur)
    return dp[1][n]   

11/13 520. 检测大写字母

依次判断三个条件
全是大写;全是小写;首字母大写,后续小写

def detectCapitalUse(word):
    """
    :type word: str
    :rtype: bool
    """
    if word==str.upper(word):
        return True
    if word==str.lower(word):
        return True
    if 'A'<=word[0]<='Z' and word[1:]==str.lower(word[1:]):
        return True
    return False   

11/14 677. 键值映射

1.map中存放key-val映射关系 覆盖储存
得到前缀后 遍历所有key 如果前缀匹配 则将val累加
2.字典树

 class MapSum1(object):

    def __init__(self):
        """
        Initialize your data structure here.
        """
        
        self.dic = {}
        

    def insert(self, key, val):
        """
        :type key: str
        :type val: int
        :rtype: None
        """
        self.dic[key]=val
        

    def sum(self, prefix):
        """
        :type prefix: str
        :rtype: int
        """
        ret = 0
        for k in self.dic.keys():
            if k.startswith(prefix):
               ret+=self.dic[k] 
        return ret
    
class MapSum(object):

    def __init__(self):
        """
        Initialize your data structure here.
        """
        
        self.dic = {}
        

    def insert(self, key, val):
        """
        :type key: str
        :type val: int
        :rtype: None
        """
        dic = self.dic
        for c in key:
            if c not in dic:
                dic[c]={}
            dic=dic[c]
        dic['end'] = val
        

    def sum(self, prefix):
        """
        :type prefix: str
        :rtype: int
        """
        ret = 0
        dic = self.dic
        print(dic)
        for c in prefix:
            if c not in dic:
                return 0
            else:
                dic = dic[c]
        l = [dic]
        while l:
            tmp = []
            for m in l:
                for k,v in m.items():
                    if k=='end':
                        ret +=v
                    else:
                        tmp.append(v)
            l = tmp
        return ret
           

你可能感兴趣的:(Exercise,leetcode,算法)