LeetCode 每日一题 2022/1/10-2022/1/16

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




1/10 306. 累加数

使用add函数将两个字符串类型的数相加
遍历开头两个数的可能性fst,snd
开头不能为0 除非只有0

def isAdditiveNumber(num):
    """
    :type num: str
    :rtype: bool
    """
    def add(a,b):#len(a)<len(b)
        if len(a)>len(b):
            a,b = b,a
        la = list(a)
        lb = list(b)
        ans = []
        jin = 0
        for i in range(1,len(la)+1):
            v = int(la[-i])+int(lb[-i])+jin
            jin = 0
            if v>9:
                v %=10
                jin = 1
            ans = [str(v)]+ans
        for j in range(len(la)+1,len(lb)+1):
            v = int(lb[-j])+jin
            jin = 0
            if v>9:
                v %=10
                jin = 1
            ans = [str(v)]+ans
        if jin>0:
            ans = [str(jin)]+ans
        return "".join(ans)     
    
    n = len(num)
    maxl = n//2
    for i in range(1,maxl+1):
        tmp = num
        for j in range(1,(n-i)//2+1):
            fst = tmp[:i]
            snd = tmp[i:i+j]
            if snd[0]=="0" and len(snd)>1:
                continue
            loc = i+j
            while loc<n:
                thd = add(fst,snd)
                ln = len(thd)
                if loc+ln==n and tmp[loc:loc+ln]==thd:
                    return True
                elif loc+ln<n and tmp[loc:loc+ln]==thd:
                    fst,snd = snd,thd
                    loc = loc+ln
                else:
                    break
    return False

1/11 1036. 逃离大迷宫

判断两点是否能够连通可以使用BFS
但由于网格过于庞大 必定超时
看到封锁的方格最多只有200个
可以思考 有n个封锁的方格 最大能够封锁的面积为(n^2)/2 当n个方格为等腰直角三角形斜边时
如果一个点在封锁区内 那么它能够到达的面积<=最大封锁面积
如果一个点能够到达的面积大于最大封锁面积 那么这个点必定没有被封锁网格封锁住
判断起点终点是否被封锁住 在判断中途有个能已经相连

def isEscapePossible(blocked, source, target):
    """
    :type blocked: List[List[int]]
    :type source: List[int]
    :type target: List[int]
    :rtype: bool
    """
    if len(blocked)==0:
        return True
    bset = set()
    for x,y in blocked:
        bset.add((x,y))
    blen = len(blocked)
    tsize = blen**2//2
    
    def isOpen(start,end):
        num = 1
        mem = set()
        mem.add((start[0],start[1]))
        l = [start]
        while l:
            tmp = []
            for x,y in l:
                for i,j in [(1,0),(0,1),(-1,0),(0,-1)]:
                    newx,newy = x+i,y+j
                    if 0<=newx<10**6 and 0<=newy<10**6:
                        if (newx,newy) not in mem and (newx,newy) not in bset:
                            if newx==end[0] and newy==end[1]:
                                return True
                            num+=1
                            tmp.append((newx,newy))
                            mem.add((newx,newy))
                            if num>tsize:
                                return True
            l = tmp[:]
        return False
    return isOpen(source,target) and isOpen(target,source)

1/12 334. 递增的三元子序列

类似LCS问题 最长上升子序列
因为只要找到三个 所以我们只需要两个变量 记录前两个数
fst,snd 单调递增 当找到大于snd的数时 则该数可以与前两个构成递增三元组
如果小于snd大于fst 则更新snd
如果小于fst 则更新fst

def increasingTriplet(nums):
    """
    :type nums: List[int]
    :rtype: bool
    """
    if len(nums)<3:
        return False
    fst = nums[0]
    snd = float("inf")
    for i in range(1,len(nums)):
        if nums[i]>snd:
            return True
        elif nums[i]>fst:
            snd = nums[i]
        else:
            fst = nums[i]
    return False

1/13 747. 至少是其他数字两倍的最大数

确定最大值 从头遍历记录最大值位置
判断所有值是否小于等于最大值一半

def dominantIndex(nums):
    """
    :type nums: List[int]
    :rtype: int
    """
    target = max(nums)
    ans = -1
    for loc,num in enumerate(nums):
        if num==target:
            ans = loc
        elif num<target and num*2>target:
            return -1
    return ans

1/14 373. 查找和最小的 K 对数字

每个数组最多涉及前K个数
先将nums1[0] + nums2[x] x=[0,k)
一共k个结果放入最小堆中
取当前最小值 numx1[i]+nums2[j] 将nums1[i+1]+nums2[j]放入堆中

def kSmallestPairs(nums1, nums2, k):
    """
    :type nums1: List[int]
    :type nums2: List[int]
    :type k: int
    :rtype: List[List[int]]
    """
    import heapq
    l = []
    heapq.heapify(l)
    len1 = min(len(nums1),k)
    len2 = min(len(nums2),k)
    for i in range(len2):
        heapq.heappush(l,(nums1[0]+nums2[i],0,i))
    ans = []
    for _ in range(k):
        if len(l)==0:
            break
        _,x,y = heapq.heappop(l)
        ans.append([nums1[x],nums2[y]])
        if x+1<len1:
            for j in range(len2):
                heapq.heappush(l,(nums1[x+1]+nums2[j],x+1,j))
    return ans

1/15 1716. 计算力扣银行的钱

第一周存 1+2+…+7=28
第二周存 2+3+…+8=35
第i周存 i+(i+1)+…+(i+6) = 21+7i
共有i周 总数=21*i+(1+2+…+i)i//27
剩余天数 第一天为i+1块

def totalMoney(n):
    """
    :type n: int
    :rtype: int
    """
    week = n//7
    day = n%7
    ans = 0
    
    ans = 21*week+(1+week)*week*7//2
    ans += (week+1+week+day)*day//2
    return ans

1/16 382. 链表随机节点

水塘抽样算法
一次遍历每个节点 对于节点i 当前选他为答案的概率为1/i (1-1/i)的概率保持答案不变
对于节点i最终的可能性:
1/i*(1-1/(i+1))(1-1/(i+2))(1-1/n)
= 1/i
(i/i+1)(i+1/i+2)…*(n-1/n)
= 1/n

class ListNode(object):
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
class Solution(object):

    def __init__(self, head):
        """
        :type head: Optional[ListNode]
        """
        self.node = head


    def getRandom(self):
        """
        :rtype: int
        """
        import random
        node,ans,i = self.node,None,0
        while node:
            if random.randint(0,i)==0:
                ans = node.val
            node,i = node.next,i+1
        return ans


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值