抓兔子

341 阅读2分钟

问题

这个问题大意是,一条直线上有 100 个洞,兔子藏在其中的一个洞里。

你一次只能查看一个洞,并且每次你查看洞的时候,兔子都会跳到它当前所在位置的相邻的洞里去。

举例来说,现在有 _ X _ _ 这四个洞,X 代表兔子的位置在第二个洞,如果你查看了第三个洞,之后兔子就可能会跳到它左边的第一个或右边第三个洞中去。

要求写出找到兔子的算法,并且给出复杂度

image.png

简单说下我的思路:减少兔子下一步的可能性,假设 在中间连续三个洞,下一步 兔子有5种可能,如果 查看这三个连续洞的中的两边任意一个洞,下一步可能是4,查看中间的洞,下一步的可能为 3,所以优先查看 中间部分 并且连续的三个洞中的中间一个洞; 没有连续的洞的情况,兔子在首位洞的时候下一步 只有一种可能,不在首位的时候 可以选择向两边跳 即有两种可能,所以 以减少 可能性的目的 优先查看 中间的。

1、查看中间的连续三个洞的中间的洞

2、中间非连续的洞

3、两遍的洞

思路有了剩下的就是写代码的事情喽:


function findRabbit(holeCount) { // holeCount 洞的个数 下标从 1 开始

    let maybeList = new Array(holeCount).fill(0).map((_, i) => i + 1)

    let index = 1

    while(maybeList.length) {

        const holeNum = selectHoleNum(maybeList, holeCount)

        const arr = maybeList.filter(item => item !== holeNum)

        const newList = nextStep(arr, holeCount)

        if(!newList.length) {

            console.log(`******** 恭喜在 第${index}次 查看第 ${holeNum} 个洞 抓到 兔子********`)

        break

        } else {

            console.log(`-----第${index}次 查看第 ${holeNum} 个洞,兔子可能在:${JSON.stringify(arr)}, 可能跳到:${JSON.stringify(newList)}-------`)

        }

        maybeList = newList

        index++

    }

}

  


function nextStep(list, holeCount) {

    const arr = Array.from(new Set(list.map(item => step(item, holeCount)).flat())).sort((a,b)=> a - b);

    return arr

}

  


function step(n, holeCount) {

    return [n -1, n + 1].filter((item)=> item > 0 && item < holeCount + 1)

}

  


function selectHoleNum(list, holeCount) { // 找到连续

    const len = list.length

    if(len === 1) {

        return list[0]

    }

    let n = -1

    for(let i = 0; i < len; i ++ ) {

        const hNum = list[i]

        if( i > 0 && i + 1 < len && list[i + 1] - list[i - 1] === 2 ) {//连续的三个洞,选择查看中间的洞,左右两边都可以跳到中间的洞,排除中间的洞,减少下次跳入的可能

            return hNum

        } else if(n < 0 && hNum > 1 && hNum < holeCount) {

            n = hNum

        }

    }

    return n

}

  


findRabbit(100)


(时间复杂度不是最优的,但是能抓到兔子,嘿嘿)

代码中验证是在 197次找到兔子;和上面的规律算出来的差1,没找到原因

476C518A-FBB9-4B70-8AA1-D756F9111C5B.png 4个洞时

6BCE2CC8-92E6-4B0C-BCAE-9079AE037AA8.png

5个洞时

1176F04E-1AB0-40C0-9798-562F8BECBA7E.png