【多源广搜】【DFS】地图中的最高点/判断二分图+浅谈Python中数组的浅拷贝和深拷贝

地图中的最高点
多源广搜的重点:确保能正确判断两个源点发生交会

判断二分图
DFS的trick:Python3 用nonlocal关键字修饰flag,可以标记是否为有效二分图
all来判断

Python中数组的浅拷贝和深拷贝:
在Python中,数组的拷贝操作可以分为浅拷贝和深拷贝两种方式:

浅拷贝(Shallow Copy)
浅拷贝创建了一个新的对象,该对象是源对象的一个副本。但是,新对象中的元素仍然是源对象元素的引用。换句话说,新对象只是源对象的一个浅层副本,其中的元素仍然指向相同的内存地址。

在Python中,可以使用切片操作或copy()函数执行浅拷贝。例如:

original_list = [1, 2, 3, [4, 5]]
shallow_copy = original_list[:]  # 使用切片操作进行浅拷贝

对于浅拷贝,当修改源对象的可变元素时,新对象也会受到影响,因为它们共享相同的引用。但是,如果修改源对象的不可变元素,例如整数或字符串,新对象不会受到影响。

深拷贝(Deep Copy)
深拷贝创建了一个全新的对象,并且递归地复制源对象及其所有嵌套对象。这意味着新对象和源对象是完全独立的,对一个对象的修改不会影响另一个对象。

在Python中,可以使用copy.deepcopy()函数执行深拷贝。例如:

import copy

original_list = [1, 2, 3, [4, 5]]
deep_copy = copy.deepcopy(original_list)  # 执行深拷贝

对于深拷贝,即使修改源对象的可变元素,新对象也不会受到影响,因为它们具有不同的内存地址。

需要注意的是,深拷贝可能会更耗费内存和处理时间,特别是当源对象包含大量嵌套对象时。因此,只有在需要真正独立的副本时才需要执行深拷贝。

总结:

  • 浅拷贝创建一个新对象,但是其中的元素仍然是源对象元素的引用。
  • 深拷贝创建一个全新的对象,并递归地复制源对象及其所有嵌套对象。
  • 对于浅拷贝,修改源对象的可变元素会影响新对象,而不可变元素不会受到影响。
  • 对于深拷贝,无论修改源对象的哪个元素,新对象都不会受到影响。

地图中的最高点:

class Solution:
    def highestPeak(self, isWater: List[List[int]]) -> List[List[int]]:
        water_tiles = []
        m = len(isWater)
        n = len(isWater[0])
        for i in range(m):
            for j in range(n):
                if isWater[i][j] == 1:  # Check for water, not 0
                    water_tiles.append((i, j))

        height = [[-1] * n for _ in range(m)]  # Initialize height grid

        queue = deque()
        for tile in water_tiles:
            x, y = tile
            height[x][y] = 0  # Set water tiles to height 0
            queue.append(tile)

        while queue:
            x, y = queue.popleft()
            for dx, dy in [(-1, 0), (1, 0), (0, 1), (0, -1)]:
                x_ = x + dx
                y_ = y + dy
                if 0 <= x_ < m and 0 <= y_ < n and height[x_][y_] == -1:
                    height[x_][y_] = height[x][y] + 1
                    queue.append((x_, y_)) 

        return height

错误的写法的反思——没有正确判断源点的交会

  1. 在原始代码中,错误地将水域的方格识别为值为0的方格。在修正后的代码中,我们检查值为1来识别水域方格。
  2. height 网格被初始化为 isWater 的浅拷贝,这将导致修改原始的 isWater 列表。在修正后的代码中,height 被初始化为一个与 isWater 相同尺寸的新网格,所有值都设置为-1。
  3. 在循环中,source 变量是不必要的。修正后的代码直接使用坐标 xy
  4. 循环中的 x_ 和 y_ 计算错误。正确的计算方法是将 dxdy 添加到 xy 上。
  5. 条件语句中的条件是检查 height[x_][y_] == 0,这只允许遍历高度为0的单元格。在修正后的代码中,条件是 height[x_][y_] == -1,允许遍历未访问过的单元格。
class Solution:
    def highestPeak(self, isWater: List[List[int]]) -> List[List[int]]:
        water_tiles = []
        m = len(isWater)
        n = len(isWater[0])
        for i in range(m):
            for j in range(n):
                if isWater[i][j] == 0:
                    water_tiles.append((i, j))
                    isWater[i][j] = 0
        height = isWater[:]
        queue = deque()
        queue.extend(water_tiles)
        while queue:
            size = len(queue)
            for i in range(size):
                source = queue.popleft()
                for dx, dy in [(-1, 0), (1, 0), (0, 1), (0, -1)]:
                    x, y = source
                    x_ = x - dx
                    y_ = y - dy
                    if (0 <= x_ < m) and (0 <= y_ < n) and height[x_][y_] == 0:
                        height[x_][y_] = height[x][y] + 1
                        queue.append((x_, y_)) 

        return height

判断二分图

class Solution:
    def isBipartite(self, graph: List[List[int]]) -> bool:
        colored = {}

        def dfs(v, color):
            if v in colored:
                return colored[v] == color
            colored[v] = color
            next_color = "B" if color == "R" else "R"
            return all(dfs(neighbour, next_color) for neighbour in graph[v])

        for vertex in range(len(graph)):
            if vertex not in colored:
                if not dfs(vertex, "R"):
                    return False
        return True

posted @ 2024-05-10 23:28  peterzh6  阅读(8)  评论(0编辑  收藏  举报