LeetCode 每日一题 2022/7/18-2022/7/24

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


目录

      • 7/18 749. 隔离病毒
      • 7/19 731. 我的日程安排表 II
      • 7/20 1260. 二维网格迁移
      • 7/21 814. 二叉树剪枝
      • 7/22 757. 设置交集大小至少为2
      • 7/23 剑指 Offer II 115. 重建序列
      • 7/24 1184. 公交站间的距离


7/18 749. 隔离病毒

BFS 模拟
搜索所有区域 遇到病毒后
广搜并将连在一起的病毒打上相同的标签-tag
同时统计这片区域下一步会影响到的邻居数量


def containVirus(isInfected):
    """
    :type isInfected: List[List[int]]
    :rtype: int
    """
    ans = 0
    m,n = len(isInfected),len(isInfected[0])
    
    while True:
        neighbors = []
        firewalls = []
        for i in range(m):
            for j in range(n):
                if isInfected[i][j]== 1:
                    l = [(i,j)]
                    tag = len(neighbors)+1
                    neighbor = set()
                    fw = 0
                    isInfected[i][j] = -tag
                    
                    while l:
                        tmp = []
                        for x,y in l:
                            for mx,my in [(0,1),(1,0),(0,-1),(-1,0)]:
                                nx,ny = x+mx,y+my
                                if 0<=nx<m and 0<=ny<n:
                                    if isInfected[nx][ny]==1:
                                        tmp.append((nx,ny))
                                        isInfected[nx][ny] = -tag
                                    elif isInfected[nx][ny]==0:
                                        fw +=1
                                        neighbor.add((nx,ny))
                        l = tmp[:]
                    neighbors.append(neighbor)
                    firewalls.append(fw)
        if not neighbors:
            break
        tag = 0
        for i in range(1,len(neighbors)):
            if len(neighbors[i])>len(neighbors[tag]):  
                tag = i
                
        ans += firewalls[tag]
        
        for i in range(m):
            for j in range(n):
                if isInfected[i][j]<0:
                    if isInfected[i][j]==-tag-1:
                        isInfected[i][j] = 2
                    else:
                        isInfected[i][j] = 1
        for i,nb in enumerate(neighbors):
            if i!=tag:
                for x,y in nb:
                    isInfected[x][y] = 1
        
        if len(neighbors)==1:
            break
    return ans


7/19 731. 我的日程安排表 II

线段树 动态开点
val记录各节点已有次数
lazy懒标记 记录该节点内子节点已有次数未下发

class MyCalendarTwo(object):

    def __init__(self):
        self.val = {}
        self.lazy = {}
        
    def update(self,start,end,l,r,idx,val):
        if start>r or end<l:
            return
        if start<=l and r<=end:
            self.val[idx] = self.val.get(idx,0)+val
            self.lazy[idx] = self.lazy.get(idx,0)+val
            return
        mid = (l+r)>>1
        self.update(start,end,l,mid,2*idx,val)
        self.update(start,end,mid+1,r,2*idx+1,val)
        v = max(self.val.get(2*idx,0),self.val.get(2*idx+1,0))
        self.val[idx] = self.lazy.get(idx,0)+v

    def book(self, start, end):
        """
        :type start: int
        :type end: int
        :rtype: bool
        """
        self.update(start,end-1,0,10**9,1,1)
        if self.val.get(1,0)>2:
            self.update(start,end-1,0,10**9,1,-1)
            return False
        return True



7/20 1260. 二维网格迁移

mn 对于grid[i][j] 标记为in+j
每个数移动k次 找到移动后的标记位

def shiftGrid(grid, k):
    """
    :type grid: List[List[int]]
    :type k: int
    :rtype: List[List[int]]
    """
    m,n = len(grid),len(grid[0])
    ans = [[0]*n for _ in range(m)]
    total = m*n
    for i in  range(m):
        for j in range(n):
            loc = (i*n+j+k)%total
            x = loc//n
            y = loc%n
            ans[x][y] = grid[i][j]
    return ans



7/21 814. 二叉树剪枝

dfs 检查两个子树
如果子树都为0 并且自身为0 返回true

class TreeNode(object):
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def pruneTree(root):
    """
    :type root: Optional[TreeNode]
    :rtype: Optional[TreeNode]
    """
    def check(node):
        if not node:
            return True
        l = check(node.left)
        if l:
            node.left = None
        r = check(node.right)
        if r:
            node.right = None
        if l and r and node.val==0:
            return True
        return False
    if check(root):
        return None
    return root



7/22 757. 设置交集大小至少为2

将intervals排序 按x[0]升序 x[1]降序
确保x[0]相同时 靠后的x[1]被前一个包含
从后往前考虑
对于排在后面的区间来说 为了和前面的区间有更多的交集
取最前面的两个数为好
使用last1,last2记录当前最靠前的两个数
对于当前的区间x来说
如果last2<=x[1]说明已有的两个数在x内 不必再添加
如果last1<=x[1]说明一个数在x内 需要添加一个 此时添加x第一个数x[0]最优 其最有可能在前一个区间内
否则 说明没有数在当前x内 需要添加两个 x[0],x[0]+1

def intersectionSizeTwo(intervals):
    """
    :type intervals: List[List[int]]
    :rtype: int
    """
    intervals.sort(key=lambda x: (x[0], -x[1]))
    ans, n = 0, len(intervals)
    last1,last2 = intervals[-1][0],intervals[-1][0]+1
    ans = 2

    for i in range(n-2,-1,-1):
        if intervals[i][1]>=last2:
            continue
        elif intervals[i][1]>=last1:
            last1,last2 = intervals[i][0],last1
            
            ans +=1
        else:
            last1,last2 = intervals[i][0],intervals[i][0]+1

            ans +=2
    return ans



7/23 剑指 Offer II 115. 重建序列

将每个子序列内相邻两个点看作一条边
将所有入度为0的加入队列 拓扑排序
如果队列内节点大于一个 则说明不唯一
如果队列元素为1个 则取出 将数字指向的每个节点入度-1

def sequenceReconstruction(nums, sequences):
    """
    :type nums: List[int]
    :type sequences: List[List[int]]
    :rtype: bool
    """
    from collections import defaultdict
    n = len(nums)
    inD = [0]*n
    m = defaultdict(list)
    for s in sequences:
        for i in range(len(s)-1):
            x,y = s[i],s[i+1]
            m[x].append(y)
            inD[y-1]+=1
    
    l = [i for i,v in enumerate(inD) if v==0]
    
    while l:
        tmp = []
        if len(l)>1:
            return False
        for x in l:
            for y in m[x+1]:
                inD[y-1]-=1
                if inD[y-1]==0:
                    tmp.append(y)
        l = tmp
    return True



7/24 1184. 公交站间的距离

先求总和total
从start向右到dest距离可以遍历得到x 从start向左到dest可以total-x


def distanceBetweenBusStops(distance, start, destination):
    """
    :type distance: List[int]
    :type start: int
    :type destination: int
    :rtype: int
    """
    n = len(distance)
    total = sum(distance)
    x = 0
    while start!=destination:
        x += distance[start]
        start = (start+1)%n
    return min(x,total-x)


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