If you have great ideas,
Let's talk!

blog

Leetcode记录「1」

leetcodeexport

1004.Max Consecutive Ones III

Sliding window

def longestOnes(self, A: List[int], K: int) -> int:
      left = right = 0
      
      for right in range(len(A)):
        # if we encounter a 0 the we decrement K
        if A[right] == 0:
          K -= 1
        # else no impact to K
        
        # if K < 0 then we need to move the left part of the window forward
        # to try and remove the extra 0's
        if K < 0:
          # if the left one was zero then we adjust K
          if A[left] == 0:
            K += 1
          # regardless of whether we had a 1 or a 0 we can move left side by 1
          # if we keep seeing 1's the window still keeps moving as-is
          left += 1
      
      return right - left + 1

对比(自己):

def longestOnes(self, nums: List[int], k: int) -> int:
        
        cont = False
        running = deque([])
        current_sum = 0
        running_max = 0 

        k_count = 0
        for num in nums:
            if num == 1:   
                if cont:
                    running[-1] += 1
                else:
                    running.append(1)
                    cont = True
            else:
                running_max = max(running_max, current_sum)
                if cont:
                    running[-1] += 1 
                    cont = False   
                else:
                    running.append(1)

                k_count += 1
                if k_count > k:
                    current_sum -= running.popleft()
            current_sum += 1
               
        return max(running_max, current_su

**241. Different Ways to Add Parentheses ****

非常重要的做题方式和思路 很长时间没有做类似的题了

def diffWaysToCompute(self, expression: str) -> List[int]:
        op_set = {"*", "+", "-"}
        dp = {}
        
        def recur(expression):
            if expression in dp:
                return dp[expression]

            retur = []

            for i in range(len(expression)):
                if expression[i] in op_set:

                    left = recur(expression[:i]) 
                    dp.setdefault(expression[:i], left)
                    right = recur(expression[i+1:])
                    dp.setdefault(expression[i+1:], left)

                    if expression[i] == "+":
                        retur += [l + r for l in left for r in right]
                    if expression[i] == "-":
                        retur += [l - r for l in left for r in right]
                    if expression[i] == "*":
                        retur += [l * r for l in left for r in right]
                    
            if not retur:
                retur = [int(expression)]

            dp[expression] = retur
            return retur
        
        return recur(expression)

2232. Minimize Result by Adding Parentheses to Expression

def minimizeResult(self, expression: str) -> str:                   #   Example:  "247+38"
                                                                        #   left, right = "247","38"
        left, right = expression.split('+')
        value = lambda s:eval(s.replace('(','*(').replace(')',')*').strip('*'))

        lft = [ left[0:i]+'('+ left[i:] for i in range(  len(left )  )] #   lft = ['(247', '2(47', '24(7']
        rgt = [right[0:i]+')'+right[i:] for i in range(1,len(right)+1)] #   rgt = ['3)8', '38)']

        return  min([l+'+'+r for l in lft for r in rgt], key = value)

2257. Count Unguarded Cells in the Grid

binary search in

def countUnguarded(self, m: int, n: int, guards: List[List[int]], walls: List[List[int]]) -> int:
        gs, ws = {tuple(g) for g in guards}, {tuple(w) for w in walls}

        # build 2 maps of all positions occupied by either a guard or a wall
        # with keys being the position's row & col indices respectively
        occ_map_by_i, occ_map_by_j = defaultdict(list), defaultdict(list)
        for (i, j) in sorted(gs.union(ws)):
            occ_map_by_i[i].append(j)
            occ_map_by_j[j].append(i)

        res = 0
        # iterate through all positions in the 2D grid
        for i in range(m):
            for j in range(n):
                if (i, j) in gs or (i, j) in ws: continue       # pos is already occupied

                row = occ_map_by_i[i]
                x = bisect.bisect(row, j)
                if x > 0 and (i, row[x-1]) in gs: continue      # has guard to its west
                if x < len(row) and (i, row[x]) in gs: continue # has guard to its east

                col = occ_map_by_j[j]
                y = bisect.bisect(col, i)
                if y > 0 and (col[y-1], j) in gs: continue      # has guard to its north
                if y < len(col) and (col[y], j) in gs: continue # has guard to its south

                res += 1    # current position is unoccupied & unguarded

        return res

2290. Minimum Obstacle Removal to Reach Corner

同样也是很久没做这个类型的 其实很常见 用greedy永远找目前最小obs路径

如果到了顶点直接就是结果

如果dfs遍历 更新所有 会很慢 没有很好的exit condition

Recursive dp → TLE

class Solution:

    def __init__(self):
        self.dp = None
        self.grid = None
        self.n = None
        self.m = None

        self.hist = {}

    def minimumObstacles(self, grid: List[List[int]]) -> int:

        self.n = len(grid)
        self.m = len(grid[0])

        # self.dp = [[float('inf')] * self.m for _ in range(self.n)]
        self.grid = {(r, i): (0 if p == 0 else 1) for r, row in enumerate(grid) for i, p in enumerate(row)}

        self.find((0, 0), 0)

        return self.hist[(self.n-1,self.m-1)]

    def find(self, pos, obs):
        if pos in self.hist and obs >= self.hist[pos]:
            return
        self.hist[pos] = obs

        if not 0 <= pos[0] < self.n or not 0 <= pos[1] < self.m:
            return

        obs += self.grid[pos]
        
        self.find((pos[0]+1, pos[1]), obs)
        self.find((pos[0]-1, pos[1]), obs)
        self.find((pos[0], pos[1]+1), obs)
        self.find((pos[0], pos[1]-1), obs)

Dijkstra’s

def minimumObstacles(self, grid: List[List[int]]) -> int:
        
        n = len(grid) 
        m = len(grid[0]) 

        dp = [[float('inf')] * m for _ in range(n)]

        dq = [(0, 0, 0)]
        direc = [(1, 0), (-1, 0), (0, 1), (0, -1)]

        while dq:
            obs, x, y = heapq.heappop(dq)

            if x == n - 1 and y == m - 1:
                return obs

            for dx, dy in direc:
                new_x, new_y = x + dx, y + dy

                if 0 <= new_x < n and 0 <= new_y < m:

                    new_obs = obs + grid[new_x][new_y]

                    if new_obs < dp[new_x][new_y]:
                        dp[new_x][new_y] = new_obs
                        heapq.heappush(dq, (new_obs, new_x, new_y))

        return -1

Dijkstra’s -→ 0-1 BFS(当edge为0或1时)

ensure to always process path with fewer obs first

prioritize 0 weight edge

为什么只有0-1可以用 → 0, 1时1加到后面可以自动排序 不需要heappush 调顺序

如果不规定edge weight 加到后面顺序会乱 破坏搜索顺序

BFS 0-1 还有的优点是不需要在queue里记录 obs 因为都是自动排序 记录在dp中

要是讲的不清楚可以看这个 —>

https://codeforces.com/blog/entry/22276

def minimumObstacles(self, grid: List[List[int]]) -> int:
    n = len(grid) 
    m = len(grid[0]) 

    dp = [[float('inf')] * m for _ in range(n)]
    dp[0][0] = 0

    dq = deque([(0, 0)])
    direc = [(1, 0), (-1, 0), (0, 1), (0, -1)]

    while dq:
        x, y = dq.popleft()
        obs = dp[x][y]

        if x == n - 1 and y == m - 1:
            return obs

        for dx, dy in direc:
            new_x, new_y = x + dx, y + dy

            if 0 <= new_x < n and 0 <= new_y < m:
                new_obs = obs + grid[new_x][new_y]
                
                if new_obs < dp[new_x][new_y]:
                    dp[new_x][new_y] = new_obs
                
                    if grid[new_x][new_y] == 0:
                        dq.appendleft((new_x, new_y))
                    else:
                        dq.append((new_x, new_y))

    return -1