2024.9.11 Python,被围绕的区域,打家劫舍,在D天内运送包裹的能力

1.被围绕的区域

给你一个 m x n 的矩阵 board ,由若干字符 ‘X’ 和 ‘O’ 组成,捕获 所有 被围绕的区域:
连接:一个单元格与水平或垂直方向上相邻的单元格连接。
区域:连接所有 ‘O’ 的单元格来形成一个区域。
围绕:如果您可以用 ‘X’ 单元格 连接这个区域,并且区域中没有任何单元格位于 board 边缘,则该区域被 ‘X’ 单元格围绕。
通过将输入矩阵 board 中的所有 ‘O’ 替换为 ‘X’ 来 捕获被围绕的区域。
示例 1:
输入:board = [[“X”,“X”,“X”,“X”],[“X”,“O”,“O”,“X”],[“X”,“X”,“O”,“X”],[“X”,“O”,“X”,“X”]]
输出:[[“X”,“X”,“X”,“X”],[“X”,“X”,“X”,“X”],[“X”,“X”,“X”,“X”],[“X”,“O”,“X”,“X”]]

from collections import deque
class Solution:
    def solve(self, board: List[List[str]]) -> None:
        """
        Do not return anything, modify board in-place instead.
        """
        nr=len(board)
        nc=len(board[0])
        def dfs(r,c):
            nr=len(board)
            nc=len(board[0])
            board[r][c]='A'
            for x,y in ([r+1,c],[r-1,c],[r,c-1],[r,c+1]):
                if 0<x<nr-1 and 0<y<nc-1 and board[x][y]=='O':
                    dfs(x,y)

        def bfs(r,c):
            q=deque([(r,c)])
            board[r][c]='A'
            while q:
                [r,c]=q.popleft()                
                for x,y in ([r+1,c],[r-1,c],[r,c-1],[r,c+1]):
                    if 0<x<nr-1 and 0<y<nc-1 and board[x][y]=='O':
                        q.append([x,y])

        for r in range(nr):
            for c in range(nc):
                if (0==r or r==nr-1 or 0==c or c==nc-1) and board[r][c]=='O':
                    bfs(r,c)
                    #dfs(r,c)

        for r in range(nr):
            for c in range(nc):
                if board[r][c]=='O':
                    board[r][c]='X'
                elif board[r][c]=='A':
                    board[r][c]='O'

逻辑是,逆向思维。在边缘的O一定不会变成X,那么就从边缘的O开始,周围的O染色为A,剩下的O就变成X了
注意,deque那里是deque([()])很烦哦

2.在D天内运送包裹的能力

class Solution:
    def shipWithinDays(self, weights: List[int], days: int) -> int:
        right=sum(weights)
        left=max(weights)

        def get_day(max_weight):
            cur_weight=0
            day=0
            index=0
            while index<len(weights):                
                if cur_weight+weights[index]<=max_weight:
                    cur_weight+=weights[index]
                    index+=1
                else:
                    cur_weight=0
                    day+=1
            day+=1
            return day
        
        while left<right:
            mid=(left+right)//2
            if get_day(mid)>days:
                left=mid+1
            elif get_day(mid)<=days:
                right=mid
        return right       

关于二分查找,还是那句话,大于等于视情况而定,以mid为中心,大了就right变mid,小了就left变mid+1,直到两个相等为止。

3.打家劫舍

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
示例 1:
输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。
示例 2:
输入:[2,7,9,3,1]
输出:12
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
偷窃到的最高金额 = 2 + 9 + 1 = 12 。

class Solution:
    def rob(self, nums: List[int]) -> int:
        dp=[0]*len(nums)
        for i in range(len(nums)):
            if i==0:
                dp[0]=nums[0]
            elif i==1:
                dp[1]=max(nums[1],dp[0])
            else:
                dp[i]=max(nums[i]+dp[i-2],dp[i-1])

        return max(dp)

标准的动态规划问题,只有两种选择,要么偷这一家,要么不偷这一家,不偷,该家的dp就是,上一家的dp,偷了就是这家的钱加上上家的钱。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值