Kotlin中MutableList复制方法及骑士跳棋最短路径代码报错求助
嘿,我来帮你搞定这两个问题——先从Kotlin里复制MutableList的方法说起,再修复骑士最少步数代码里的bug!
一、Kotlin中复制MutableList的正确姿势
要复制MutableList,核心是要创建新的列表实例,而不是直接引用原列表(不然修改新列表会影响原列表)。常用的几种方式:
- 最简洁的方式:
toMutableList():直接生成原列表的浅拷贝副本,对于Pair这种数据类完全适用:val copiedList = originalMutableList.toMutableList() - 用ArrayList构造器:因为Kotlin里
MutableList的常用实现就是ArrayList,直接把原列表传入构造器就能创建副本:val copiedList = ArrayList(originalMutableList) - 展开数组方式:把原列表转成数组后,用展开运算符传入
mutableListOf:val copiedList = mutableListOf(*originalMutableList.toTypedArray())
二、骑士最少步数问题的代码修复
你的代码出现两个问题的根源,都是已访问列表的传递方式不对,我们一步步拆解:
为什么原代码里第二个if永远不执行?
当你写val v = visited时,v和visited是同一个MutableList的引用——也就是说,你在第一个if分支里执行v.add(Pair(i,j)),其实是修改了原递归栈里的visited列表。等走到第二个if分支时,当前位置已经被标记为已访问,自然永远进不去分支里的println。
为什么改成toMutableList()会无限循环?
用toMutableList()确实会创建独立的列表,但你的代码逻辑里,没有在进入递归前判断当前位置是否已经被访问过。不同的递归分支各自维护自己的已访问列表,导致同一个位置可能被不同分支反复访问,程序就会陷入循环,永远找不到终止条件。
修复后的代码&思路
我给你调整了代码逻辑,核心是:
- 先判断当前位置是否合法、是否已被访问,不满足直接返回-1;
- 每次递归都创建新的已访问列表副本,添加当前位置后再传递给下一层,避免分支间互相干扰;
- 补全了骑士的8种移动方式,确保不会遗漏路径。
修复后的代码:
// 先实现棋盘合法性判断(假设棋盘是1-based索引,尺寸为board) fun isValid(pos: Pair<Int, Int>, board: Int): Boolean { val (x, y) = pos return x in 1..board && y in 1..board } fun knightSteps( i: Int, j: Int, a: Int, b: Int, board: Int, c: Int, d: Int, visited: MutableList<Pair<Int, Int>>, steps: Int ): Int { // 终止条件:到达终点,返回当前步数 if (i == c && j == d) return steps val currentPos = Pair(i, j) // 先检查当前位置是否合法,或者已经被访问过 if (!isValid(currentPos, board) || currentPos in visited) return -1 // 创建已访问列表的副本,添加当前位置(不修改原列表) val newVisited = visited.toMutableList() newVisited.add(currentPos) // 骑士的8种可能移动方向 val allMoves = listOf( Pair(a, b), Pair(a, -b), Pair(-a, b), Pair(-a, -b), Pair(b, a), Pair(b, -a), Pair(-b, a), Pair(-b, -a) ) val validSteps = mutableListOf<Int>() for ((dx, dy) in allMoves) { val nextResult = knightSteps(i + dx, j + dy, a, b, board, c, d, newVisited, steps + 1) if (nextResult != -1) { validSteps.add(nextResult) } } // 没有可行路径返回-1,否则返回最小步数 return validSteps.minOrNull() ?: -1 }
额外小建议
其实这个问题用**广度优先搜索(BFS)**会更高效,也更适合找最短路径——DFS递归可能会因为路径过深导致栈溢出,而BFS是逐层遍历,找到终点时的步数就是最少步数。如果感兴趣的话,可以试试用队列实现BFS版本哦!
内容的提问来源于stack exchange,提问作者SATHWIK MATSA
相关产品推荐
相关产品推荐

