【问题标题】:Finding Rotation point using binary search, why compare with the first element?使用二进制搜索查找旋转点,为什么要与第一个元素进行比较?
【发布时间】:2020-06-11 09:38:09
【问题描述】:

所以我有这个问题是我从面试准备课程中购买的,我在这里也有解决方案。我知道我们正在使用二进制搜索来查找目标。该数组包含不同的单词,目标是以 a 开头的单词。我最初的方法是与 i-l 和 i +1 进行比较。如果 i - 1 大于 i 并且 i+1 小于 i 那么我们知道 i 是目标。但解决方案是做一些我不明白的事情。问题来了

我打开字典到中间的一页并开始翻阅,寻找我不知道的单词。我将每个我不知道的单词放在我在内存中创建的巨大数组中增加索引。当我到达字典的末尾时,我从头开始做同样的事情,直到到达我开始的页面。

现在我有一个单词数组,大部分都是按字母顺序排列的,除了它们从字母表中间的某个位置开始,到达末尾,然后从字母表的开头开始。换句话说,这是一个按字母顺序排列的数组,已经“旋转”过。例如:

String[] words = new String[]{
        "ptolemaic",
        "retrograde",
        "supplant",
        "undulate",
        "xenoepist",
        "asymptote",  // <-- rotates here!
        "babka",
        "banoffee",
        "engender",
        "karpatka",
        "othellolagkage",
};

写一个方法来查找“旋转点”的索引,这是我从字典的开头开始工作的地方。这个数组很大(有很多我不认识的词)所以我们要在这里高效。

解决方法如下

解决方案 这是二进制搜索的修改版本。在每次迭代中,如果我们正在查看的项目大于第一项,我们就向右走,如果我们正在查看的项目小于第一项,我们就向左走。

我们跟踪旋转点的上下界,称它们为 floorIndex 和 ceilingIndex(最初我们称它们为“地板”和“天花板”,但因为我们没有在名称中暗示类型,所以我们感到困惑并创建错误)。当 floorIndex 和 ceilingIndex 直接相邻时,我们知道 floor 是我们从字典开头开始之前添加的最后一项,而天花板是我们之后添加的第一项。

  public static int findRotationPoint(String[] words) {
    final String firstWord = words[0];

    int floorIndex = 0;
    int ceilingIndex = words.length - 1;

    while (floorIndex < ceilingIndex) {

        // guess a point halfway between floor and ceiling
        int guessIndex = floorIndex + ((ceilingIndex - floorIndex) / 2);

        // if guess comes after first word or is the first word
        if (words[guessIndex].compareTo(firstWord) >= 0) {
            // go right
            floorIndex = guessIndex;
        } else {
            // go left
            ceilingIndex = guessIndex;
        }

        // if floor and ceiling have converged
        if (floorIndex + 1 == ceilingIndex) {

            // between floor and ceiling is where we flipped to the beginning
            // so ceiling is alphabetically first
            break;
        }
    }

    return ceilingIndex;
}

我们为什么要与 words[0] 进行比较?我们知道 words[0] 不是目标,因为它已被转移。 假设我们有 p,r,s,u,x,a,b,c,e,k,o。我们知道 a 是中间的。由于 p > a,我们将上限设置为 a。然后我们再次将 p 与 s 进行比较。所以它错过了目标。 我只是不明白这一点。请任何帮助将不胜感激

【问题讨论】:

    标签: java binary-search


    【解决方案1】:

    这样做是为了明白,旋转点在哪里。

    让我们看看你的例子:

    String[] words = new String[]{
        "ptolemaic",
        "retrograde",
        "supplant",
        "undulate",
        "xenoepist",
        "asymptote",  // <-- rotates here!
        "babka",
        "banoffee",
        "engender",
        "karpatka",
        "othellolagkage",
    };
    

    比较words[0](即ptolemaic)和words[guessIndex](即asymptote)将告诉您阵列旋转/移动的方向。

    可能是这样的:

    [1 2 3 4 5 6 7] // no rotation
    
    [6 7 1 2 3 4 5] // biggest is left to the center
    
    [2 3 4 5 6 7 1] // smallest is right to the center
    

    通过了解您的最大/最小在哪里,您可以了解您需要继续搜索的方向。

    希望这会有所帮助。

    【讨论】:

    • 您好,谢谢您的回复。但我仍然不明白代码。所以我们比较p和a,看p的猜测值是最大值?现在 p 是最大值,a 成为上限。但是然后我们再次比较 p 和 s?我们需要一个解决方案,但是当我按照代码操作时,我没有得到一个.....
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-17
    • 1970-01-01
    • 2017-04-09
    • 1970-01-01
    • 2022-11-25
    • 2018-11-12
    相关资源
    最近更新 更多