You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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. 先判断当前位置是否合法、是否已被访问,不满足直接返回-1;
  2. 每次递归都创建新的已访问列表副本,添加当前位置后再传递给下一层,避免分支间互相干扰;
  3. 补全了骑士的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:36:54