请教一下大佬们二维矩阵的 DFS 问题,不知道为什么总是报错

2023-11-14 16:50:46 +08:00
 magic3584

业务场景:

有个二维矩阵 513 * 513 ,取值只有 0 或 1 ,根据值绘图,0 白色 1 黑色。 现在需要把不规则的黑色绘制成矩形,如下图:

代码如下:

func findConnectedRegion(matrix: [[Int]]) -> [[(Int, Int)]] {
        var result: [[(Int, Int)]] = []
        //    var visited: Set<(Int, Int)> = []
        var visited: Set<String> = []
        let numRows = matrix.count
        let numCols = matrix[0].count
        
        for i in 0..<matrix.count {
            for j in 0..<matrix[0].count {
                let position = (i, j)
                let str = String(i)+"-"+String(j)
                if matrix[i][j] == 1 && !visited.contains(str) {
                    var region: [(Int, Int)] = []
                    dfs(matrix: matrix, rows: numRows,cols: numCols,position: position, visited: visited, region: &region)
                    result.append(region)
                }
            }
        }
        
        return result
    }
    
    func dfs(matrix: [[Int]],rows:Int,cols:Int,position: (Int, Int), visited: Set<String>, region: inout [(Int, Int)]) {
//        let numRows = matrix.count
//        let numCols = matrix[0].count
        
        let numRows = rows
        let numCols = cols
        
        let (row, col) = position
        self.str = String(position.0)+"-"+String(position.1)
        
        // Check if the current position is within bounds and is part of the region
        guard row >= 0, row < numRows, col >= 0, col < numCols, matrix[row][col] == 1, !visited.contains(str) else {
            return
        }
        
        self.visited.insert(str)
        region.append(position)
        
        // Explore neighbors in all four directions
        dfs(matrix: matrix,rows: numRows,cols: numCols, position: (row - 1, col), visited: visited, region: &region)  // Up
        dfs(matrix: matrix, rows: numRows,cols: numCols,position: (row + 1, col), visited: visited, region: &region)  // Down
        dfs(matrix: matrix, rows: numRows,cols: numCols,position: (row, col - 1), visited: visited, region: &region)  // Left
        dfs(matrix: matrix, rows: numRows,cols: numCols,position: (row, col + 1), visited: visited, region: &region)  // Right
    }

好几处局部变量改成了属性,但还是不同位置报相同的错:Thread 1: EXC_BAD_ACCESS (code=2, address=0x16b6a7fc0)

完全不知道问题出在哪了,请大佬指点

1536 次点击
所在节点    iDev
18 条回复
magic3584
2023-11-14 16:51:58 +08:00
一楼请喵大 @onevcat
iOCZS
2023-11-14 18:11:14 +08:00
要进行图像分割,确定哪一些点是一个整体的,那么获取最小 x ,最大 x 以及最小 y 和最大 y 就能圈定这个矩形了。
nagisaushio
2023-11-14 18:16:32 +08:00
self.visited.insert?
magic3584
2023-11-14 18:24:19 +08:00
@iOCZS #2
是,现在用的 DFS 去划分多个区域。
使用 513*513 的随机矩阵没啥问题。实际情况可能是递归太多爆栈了,可能

所以还可以怎么去确定这个区域呢?
magic3584
2023-11-14 18:25:19 +08:00
@nagisaushio #3
本来用的局部变量,但是一直报错,改成全局了以后,别的地方又报错了[笑哭]
bing89757
2023-11-14 19:24:00 +08:00
没接触过,不过我感觉找边界就行了吧 找到后再取每个边界的最大最小值 就可以了
hefish
2023-11-14 19:27:32 +08:00
我想应该是 先遍历找起点,找到起点之后,找联通,凡是联通的都记录下来,表示是一个形状里面的,联通找完之后,继续遍历,找下一个起点,直到所有点找完。。
churchill
2023-11-14 19:36:18 +08:00
先找联通区域呀,BFS ,然后每个联通区域算包围盒
Yuhyeong
2023-11-14 19:57:31 +08:00
@magic3584 在同一个地址出报错,有没有可能是因为之前运行的时候内存没有处理,之前写题,这种情况偶尔会见到。
czfy
2023-11-14 20:09:30 +08:00
试试这样?


func findConnectedRegions(matrix: [[Int]]) -> [[[(Int, Int)]]] {

var result: [[[(Int, Int)]]] = []

for i in 0..<matrix.count {
for j in 0..<matrix[0].count {

if matrix[i][j] == 1 {

var region: [(Int, Int)] = []
var visited = Set<(Int, Int)>()

dfs(matrix: matrix, position: (i, j), visited: &visited, region: &region)

let bound = getRegionBounds(region)
result.append(bound)

}

}
}

return result

}

func dfs(matrix: [[Int]], position: (Int, Int), visited: inout Set<(Int, Int)>, region: inout [(Int, Int)]) {

let (row, col) = position

guard row >= 0, row < matrix.count, col >= 0, col < matrix[0].count, matrix[row][col] == 1, !visited.contains((row, col)) else {
return
}

visited.insert((row, col))
region.append((row, col))

dfs(matrix: matrix, position: (row-1, col), visited: &visited, region: &region)
dfs(matrix: matrix, position: (row+1, col), visited: &visited, region: &region)
// ...

}

func getRegionBounds(_ region: [(Int, Int)]) -> [(Int, Int)] {
// return bounding box
}
magic3584
2023-11-15 09:02:54 +08:00
@bing89757 #6
@hefish #7
@churchill #8
第一个方法就是先找联通区域。用个简单的矩阵没问题,现在是 513*513 的,里面有好几片联通区域(人像),可能导致递归太深栈溢出了
magic3584
2023-11-15 09:03:56 +08:00
@Yuhyeong #9
不是相同地址,是不同地址但是类似的错 Thread 1: EXC_BAD_ACCESS (code=2,
应该还是内存问题
magic3584
2023-11-15 09:06:27 +08:00
@czfy #10
您这是 chatGPT 吧。
**var visited = Set<(Int, Int)>()** swift 没这种写法,所以我改成了用 string
QingchuanZhang
2023-11-15 11:34:41 +08:00
为什么不 bfs ?
magic3584
2023-11-15 11:53:35 +08:00
@QingchuanZhang #14
我把 DFS 里 UP 那一行注释掉就好了,不知道为什么。。。
BFS 的话我得问问 chatGPT
churchill
2023-11-15 12:30:29 +08:00
@magic3584 找联通区域用 BFS 的思路我想不存在栈溢出的问题,吃完饭我来试试
churchill
2023-11-15 13:05:14 +08:00
https://codesandbox.io/s/focused-cloud-zrpxfx
简单试了下,js 写的,将就看吧
magic3584
2023-11-15 14:03:33 +08:00
@churchill #17
感谢大佬,那个 floodFill 看着有点复杂。。。tmp 怎么只有 push 没有 pop 。。。
结果就是不知道怎么应用在我这个问题上

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/991869

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX