LeetCode 每日一题 2023/9/18-2023/9/24

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




9/18 337. 打家劫舍 III

对于一节node有两种情况 偷 或者 不偷
lrrob函数返回 偷这个node 和 不偷这个node 能够得到的最佳情况
如果这个点为空 那么 偷不偷的情况都是0
获得改点左右子节点的情况 lrob,lnot(偷/不偷左节点) rrob,rnot(偷/不偷右节点)
如果要偷 那么对于就不能偷他的左右子节点 得到 val+lnot+rnot
如果不偷 那么对于左右子节点可以选择偷或不偷 选最大值 max(lrob,lnot)+max(rrob,rnot)

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

def rob(root):
    """
    :type root: TreeNode
    :rtype: int
    """
    def lrrob(node):
        if not node:
            return 0,0
        lrob,lnot = lrrob(node.left)
        rrob,rnot = lrrob(node.right)
        
        return node.val+lnot+rnot, max(lrob,lnot)+max(rrob,rnot)
    
    return max(lrrob(root))



9/19 2560. 打家劫舍 IV

二分 偷窃能力必定在min(nums),max(nums)的区间内
对与偷窃能力m
遍历所有房子
只关心偷或者不偷 所以遇到能偷的就偷 统计能偷的数量

def minCapability(nums, k):
    """
    :type nums: List[int]
    :type k: int
    :rtype: int
    """
    l,r = min(nums),max(nums)
    while l<r:
        m = (l+r)//2
        pre,take=0,0
        for num in nums:
            if pre:
                pre=0
                continue
            if num<=m:
                take+=1
                pre=1
            if take>=k:
                break
        if take>=k:
            r = m
        else:
            l = m+1
    return l



9/20 LCP 06. 拿硬币

减少次数 每次尽量拿两枚
对于一对n个硬币 需要拿取(n+1)//2次


def minCount(coins):
    """
    :type coins: List[int]
    :rtype: int
    """
    ans = 0
    for c in coins:
        ans +=(c+1)//2
    return ans


9/21 2603. 收集树中金币

如果一个节点度数为1 即只有一个邻居 可以称作叶子节点
如果一个叶子节点没有金币 则这叶子节点可以直接去除
直至所有叶子节点都包含金币
由于可以直接收集距离为2以内的金币 所以我们只需要访问叶子节点的父节点的父节点
将所有叶子节点去除 再将新叶子节点去除 剩余的是我们必须要访问的节点
因为要回到出发点 所以每条边必定走两次

def collectTheCoins(coins, edges):
    """
    :type coins: List[int]
    :type edges: List[List[int]]
    :rtype: int
    """
    n= len(coins)
    g = [[] for _ in range(n)]
    for x,y in edges:
        g[x].append(y)
        g[y].append(x)
    deg = list(map(len,g))
    
    eg = n-1
    l = []
    for i,(d,c) in enumerate(zip(deg,coins)):
        if d==1 and c==0:
            l.append(i)
    while l:
        eg-=1
        for y in g[l.pop()]:
            deg[y]-=1
            if deg[y]==1 and coins[y]==0:
                l.append(y)
                
    for i,(d,c) in enumerate(zip(deg,coins)):
        if d==1 and c:
            l.append(i)
    eg -= len(l)
    for x in l:
        for y in g[x]:
            deg[y]-=1
            if deg[y]==1:
                eg-=1
    return max(eg*2,0)



9/22 2591. 将钱分给最多的儿童

如果钱少于儿童 则没有分配方案
先将每个儿童分配1元 然后查看还能分配出几个7元
处理特殊情况

def distMoney(money, children):
    """
    :type money: int
    :type children: int
    :rtype: int
    """
    if money<children:
        return -1
    left = money-children
    ans = min(children,left//7)
    if ans+1==children and ans*8+4==money:
        ans-=1
    if ans==children and ans*8!=money:
        ans-=1
    return ans



9/23 1993. 树上的操作

locked[i]用来记录节点i被哪一个用户上锁
parent[i]记录节点i的父节点
children[i] 记录节点i的子节点
dfs判断子孙节点是否由上锁的

class LockingTree(object):

    def __init__(self, parent):
        """
        :type parent: List[int]
        """
        n=len(parent)
        self.locked = [-1]*n
        self.parent = parent
        self.children = [[] for _ in range(n)]
        for s,p in enumerate(parent[1:],1):
            self.children[p].append(s)


    def lock(self, num, user):
        """
        :type num: int
        :type user: int
        :rtype: bool
        """
        if self.locked[num]==-1:
            self.locked[num]=user
            return True
        return False


    def unlock(self, num, user):
        """
        :type num: int
        :type user: int
        :rtype: bool
        """
        if self.locked[num]==user:
            self.locked[num]=-1
            return True
        return False


    def upgrade(self, num, user):
        """
        :type num: int
        :type user: int
        :rtype: bool
        """
        global find
        def dfs(x):
            global find
            for c in self.children[x]:
                if self.locked[c]!=-1:
                    self.locked[c]=-1
                    find = True
                dfs(c)
        x=num
        while x!=-1:
            if self.locked[x]!=-1:
                return False
            x = self.parent[x]
        
        find=False
        dfs(num)
        if not find:
            return False
        self.locked[num]=user
        return True



9/24 146. LRU 缓存

fr存储最近是用过的key
kw存储key对应的value

from collections import defaultdict
class LRUCache:

    def __init__(self, capacity: int):
        self.cp = capacity
        self.kw = defaultdict(int)
        self.fr = []
        

    def get(self, key: int) -> int:
        if key in self.kw:
            self.fr.remove(key)
            self.fr.insert(0,key)
            return self.kw[key]
        else:
            return -1

    def put(self, key: int, value: int) -> None:
        if key in self.kw or len(self.kw)<self.cp:
            self.kw[key] = value
            if key in self.fr:
                self.fr.remove(key)
            self.fr.insert(0,key)
        else:
            k = self.fr[-1]
            print(k,key)
            self.kw.pop(k)
            self.kw[key] = value
            self.fr.remove(k)
            self.fr.insert(0,key)



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值