LeetCode 每日一题 2022/5/23-2022/5/29

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




5/23 675. 为高尔夫比赛砍树

树必须从低到高砍 所以需要将树的高度从小到大排序 大于1的为树 trees
依次从低到高走过每一棵树 每两个数之间走最小步数可以使得总和最小
BFS计算两棵树之间最短距离 如果距离为-1 说明两树之间没有通路
高度为1为土地不需要砍

def cutOffTree(forest):
    """
    :type forest: List[List[int]]
    :rtype: int
    """
    m,n=len(forest),len(forest[0])
    trees = []
    for i in range(m):
        for j in range(n):
            if forest[i][j]>1:
                trees.append((forest[i][j],i,j))
    trees.sort()
    def bfs(sx,sy,tx,ty):
        l = [(0,sx,sy)]
        mem = set()
        mem.add((sx,sy))
        while l:
            tmp = []
            for d,x,y in l:
                if x==tx and y==ty:
                    return d
                for nx,ny in [(x-1,y),(x+1,y),(x,y-1),(x,y+1)]:
                    if 0<=nx<m and 0<=ny<n and forest[nx][ny] and (nx,ny) not in mem:
                        mem.add((nx,ny))
                        tmp.append((d+1,nx,ny))
            l = tmp[:]
        return -1
    ans = 0
    prex,prey=0,0
    for _,x,y in trees:
        d = bfs(prex,prey,x,y)
        if d<0:
            return -1
        print(prex,prey,"->",x,y,"=",d)
        ans +=d
        prex,prey = x,y
    return ans



5/24 965. 单值二叉树

遍历二叉树判断每一个值是否一致 使用广搜


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

def isUnivalTree(root):
    """
    :type root: TreeNode
    :rtype: bool
    """
    v = root.val
    l = [root]
    while l:
        tmp = []
        for node in l:
            if node.val!=v:
                return False
            if node.left:
                tmp.append(node.left)
            if node.right:
                tmp.append(node.right)
        l = tmp
    return True


5/25 467. 环绕字符串中唯一的子字符串

对于字符x 记录以x结尾的最长连续长度 即是x结尾的子串个数

def findSubstringInWraproundString(p):
    """
    :type p: str
    :rtype: int
    """
    m = {}
    n = 0
    for i,c in enumerate(p):
        if i>0 and (ord(c)-ord(p[i-1]))%26==1:
            n+=1
        else:
            n = 1
        m[c] = max(m.get(c,0),n)
    return sum(m.values())



5/26 699. 掉落的方块

1.方块个数<=1000 遍历每一个方块
对于方块x 如果与之前的方块范围有重合 则他的高度h[x]=max(h[与x重合的方块])+x边长
maxv记录当前最高高度 每次计算h[x] 更新maxv并加入ans中
2.线段树
动态开点: 初始只建立根节点 访问子区间时才生成区间内子节点
懒标记: 更新时遇到包含整个区间的节点打上标记,需要查询时下传到左右子节点,该节点标记清零
学习 https://leetcode.cn/problems/falling-squares/solution/-by-lcbin-5rop/
3.方块个数<=1000
将每个方块的左右两点排序
li记录排序后的每个点当前高度
对于x方块 在left,right范围内的li中取最大值maxv hx = maxv + 当前方块边长
更新当前最大高度maxh
更新范围内li的值

def fallingSquares1(positions):
    """
    :type positions: List[List[int]]
    :rtype: List[int]
    """
    def overlap(x,y):
        l = x
        r = y
        if x[0]>y[0]:
            l = y
            r = x
        return l[0]+l[1]>r[0]
    h = [positions[0][1]]
    ans = [positions[0][1]]
    maxv = positions[0][1]
    for x in positions[1:]:
        maxh = 0
        for i in range(len(h)):
            if overlap(positions[i],x):
                maxh = max(maxh,h[i])
        h.append(maxh+x[1])
        maxv = max(maxv,maxh+x[1])
        ans.append(maxv)
    return h
                
def fallingSquares2(positions):
    """
    :type positions: List[List[int]]
    :rtype: List[int]
    """
    class Node:
        def __init__(self,l,r):
            self.left = None
            self.right = None
            self.l = l
            self.r = r
            self.h = 0
            self.add = 0
            self.mid = l+(r-l)//2
    class SegmentTree:
        def __init__(self):
            self.root = Node(1,int(1e9))
        
        def query(self,l,r,node=None):
            if l>r:
                return 0
            if not node:
                node = self.root
            if node.l>=l and node.r<=r:
                return node.h
            self.pushdown(node)
            h = 0
            if l<=node.mid:
                h = max(h,self.query(l,r,node.left))
            if r>node.mid:
                h = max(h,self.query(l,r,node.right))
            return h
        def pushdown(self,node):
            if not node.left:
                node.left = Node(node.l,node.mid)
            if not node.right:
                node.right = Node(node.mid+1,node.r)
            if node.add:
                node.left.h = node.add
                node.right.h = node.add
                node.left.add = node.add
                node.right.add = node.add
                node.add = 0
        def modify(self,l,r,h,node=None):
            if l>r:
                return
            if not node:
                node = self.root
            if node.l>=l and node.r<=r:
                node.h = h
                node.add = h
                return
            self.pushdown(node)
            if l<=node.mid:
                self.modify(l,r,h,node.left)
            if r>node.mid:
                self.modify(l,r,h,node.right)
            self.pushup(node)
        def pushup(self,node):
            node.h = max(node.left.h,node.right.h)
            
    ans = []
    maxh = 0
    tr = SegmentTree()
    for left,lg in positions:
        right = left+lg-1
        h = tr.query(left,right)+lg
        maxh = max(maxh,h)
        ans.append(maxh)
        tr.modify(left,right,h)
    return ans
            
def fallingSquares3(positions):
    """
    :type positions: List[List[int]]
    :rtype: List[int]
    """
    pos = set()
    for left,lg in positions:
        pos.add(left)
        pos.add(left+lg)
    pos = sorted(pos)
    ind = {}
    for i,num in enumerate(pos):
        ind[num] = i
    li = [0]*len(pos)
    ans = []
    maxh = 0
    for left,lg in positions:
        idxl = ind[left]
        idxr = ind[left+lg]
        h = max(li[idxl:idxr])+lg
        maxh = max(maxh,h)
        ans.append(maxh)
        for i in range(idxl,idxr):
            li[i] = h
    return ans



5/27 面试题 17.11. 单词距离

1.m[x]记录单词x出现的所有位置
两个单词的出现的位置为l1,l2
遍历其中较短的位置队列 用二分在另一个队列中找出离这个位置最近的距离
2.记录两个单词最近出现的位置index1 index2
当某个单词位置更新时 获得新的距离 判断是否变短

def findClosest(words, word1, word2):
    """
    :type words: List[str]
    :type word1: str
    :type word2: str
    :rtype: int
    """
    from collections import defaultdict
    m = defaultdict(list)
    for i in range(len(words)):
        w = words[i]
        m[w].append(i)
        
    l1 = m[word1]
    l2 = m[word2]
    
    if len(l1)>len(l2):
        l1,l2=l2,l1
    def find(num,li):
        if num<li[0]:
            return li[0]-num
        if num>li[-1]:
            return num-li[-1]
        l,r = 0,len(li)-1
        while l<=r:
            mid = (l+r)>>1
            if li[mid]<num:
                l = mid+1
            else:
                r = mid-1
        return min(li[l]-num,num-li[l-1])
    ans = float('inf')
    for i in l1:
        tmp = find(i,l2)
        ans =min(ans,tmp)
        if ans==1:
            return ans
    return ans

def findClosest2(words, word1, word2):
    """
    :type words: List[str]
    :type word1: str
    :type word2: str
    :rtype: int
    """
    ans = len(words)
    ind1,ind2 = -1,-1
    for i,word in enumerate(words):
        if word==word1:
            ind1 = i
        elif word==word2:
            ind2 = i
        if ind1>=0 and ind2>=0:
            ans = min(ans,abs(ind1-ind2))
    return ans



5/28 1021. 删除最外层的括号

left代表当前待匹配的左括号个数
cur为当前字符串
如果为0说明匹配完成 当前为一个原语
一个原语字符串首位字符必定为一左一右括号
去除左右两边括号即可

def removeOuterParentheses(s):
    """
    :type s: str
    :rtype: str
    """
    ans = ""
    cur = ""
    left = 0
    for c in s:
        if c=="(":
            left +=1
        else:
            left -=1
        cur += c
        if left ==0:
            ans += cur[1:-1]
            cur = ""
    return ans



5/29 468. 验证IP地址

分别判断是否是ipv4 ipv6 如果都不是则为neither

def validIPAddress(queryIP):
    """
    :type queryIP: str
    :rtype: str
    """
    def isIp4(s):
        l = s.split(".")
        if len(l)!=4:
            return False
        for string in l:
            if not string.isdigit() or (len(string)>1 and string[0]=='0'):
                return False
            v = int(string)
            if v<0 or v>255:
                return False
        return True
    def isIp6(s):
        l = s.split(":")
        if len(l)!=8:
            return False
        for string in l :
            if len(string)<1 or len(string)>4:
                return False
            for c in string:
                if "0"<=c<="9"or "a"<=c<="f" or "A"<=c<="F":
                    continue
                else:
                    return False
        return True
            
    
    if isIp4(queryIP):
        return "IPv4"
    elif isIp6(queryIP):
        return "IPv6"
    else:
        return "Neither"



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值