二进制搜索算法

by Divya Godayal

通过Divya Godayal

二进制搜索的一个扭曲故事 (A twisted tale of Binary Search)

Awesome. That’s how I feel right now. Writing my first solo tech article.

太棒了 那就是我现在的感觉。 写我的第一篇个人技术文章。

I must say I have a lot to share with you guys, and have a lot more to learn as well. So without any further ado, lets get to it. And yes, hold on tight — ‘cause there is a twist in the tale. ?

我必须说,我有很多可以与你们分享的东西,并且还有很多东西要学习。 因此,事不宜迟,让我们开始吧。 是的,请紧紧握住-因为故事有个转折。 ?

二元搜寻 (Binary Search)

All of us have heard of the classic 2 Eggs and 100 Stories problem. I have something similar for you.

我们所有人都听说过经典的2个鸡蛋和100个故事问题。 我有类似的东西给你。

You have a 100 story building with a rule:

您有一个具有规则的100层建筑:

People with pets can only occupy top floors

People with pets can only occupy top floors

Your friend wishes to buy an apartment in this building. She is too scared of pets to live near them, but you love them. She asked if you can help her find out where exactly the pet friendly floors start. She wants to explore all of the different options available, and so you need to find out which floors starting from the ground up are the ones that don’t allow pets.

您的朋友希望在此建筑物中购买公寓。 她太怕宠物了,不能住在附近,但你爱它们。 她问您是否可以帮助她找出宠物友好地板的确切位置。 她想探索所有可用的不同选项,因此您需要找出从头开始的哪些楼层不允许宠物入内。

The building management folks are on a holiday. On every floor, there is a sign board next to the elevator telling you if the floor is pet friendly or not. But you are too lazy to stop at every floor to check the pet sign board since the lift is so slow.

建筑管理人员正在度假。 在每层楼上,电梯旁边都有一个告示牌,告诉您该楼层是否可养宠物。 但是,由于电梯太慢,您懒得在每个楼层停下来检查宠物指示牌。

What do you do?

你是做什么?

The lift takes almost a minute at every floor to stop and then start again. Yes that’s how bad it is. But between the floors, navigation is pretty smooth. You have to get this done quickly.

电梯在每层都需要花费近一分钟的时间才能停止,然后重新开始。 是的,那真是太糟糕了。 但是在楼层之间,导航非常流畅。 您必须快速完成此任务。

How do you go about it ?

你如何去做?

迭代法 (Iterative approach)

One naïve approach to this would be to start at the very bottom of the building (the ground floor) and keep stopping the lift at every single floor to check the sign that floor has posted. You stop when you find the pet friendly sign.

一种简单的方法是从建筑物的最底端(底层)开始,并在每一层都停下电梯,以检查该层已张贴的迹象。 找到宠物友好标志时,您将停下来。

Best case is that the ground floor has the pet sign. Meaning the entire building has pets. No way your friend would buy an apartment here.

最好的情况是一楼有宠物标志。 意思是整个建筑都养宠物。 您的朋友绝对不会在这里购买公寓。

Average case is that you go to the 50th floor, stopping at every floor in between, and finally find a pet sign board. So your friend can buy one from 1–49.

一般情况是,您去了50楼,停在中间的每一层,最后找到一个宠物告示板。 这样您的朋友可以从1到49购买一个。

Worst case scenario would be you reaching the 100th floor, stopping at every floor on the way up, only to find out that there are no pet sign boards in the entire building. So your friend can buy any apartment from 1–100, but who cares, it took you almost two hours to find that out. ? ?.

最糟糕的情况是,您到达100楼,在上升的每一层都停下来,却发现整个建筑物中没有宠物告示板。 因此,您的朋友可以购买1100至100欧元之间的任何公寓,但谁在乎,您花了将近两个小时才找到答案。 ? ?

Algorithmically, given an array of 100 boolean values, the index of the array represents building floors and a 0 represents a floor where no pets are allowed while a 1 represents a floor where pets would be allowed. From the rule of the building, the array would be of the form

从算法上讲,给定一个包含100个布尔值的数组,该数组的索引表示建筑物楼层,0表示不允许宠物进入的楼层,而1表示允许宠物进入的楼层。 根据建筑物的规则,数组的形式为

000... 1111...

that is, all 0s followed by all 1s, because only the top floors can be the ones where pets are allowed.

也就是说,全0后面全为1,因为只有顶层可以带宠物。

Given this array, we need to find the first index where there is a 1 . A linear search algorithm for this problem would be as simple as iterating over the array and looking for a 1 and returning when we find one.

给定此数组,我们需要找到第一个索引为1 。 解决这个问题的线性搜索算法就像在数组上迭代并寻找1并在找到一个返回时一样简单。

As expected, the complexity of this algorithm would be O(n) where n = 100 for our specific building example. You need to come up with something faster than this. Stopping at every floor is not feasible, as it would take you a lot of time to cover the entire building in the worst case.

不出所料,此算法的复杂度为O(n) ,其中对于我们的特定建筑示例,n = 100。 您需要提出比这更快的方法。 在每一层都停下来是不可行的,因为在最坏的情况下,要花费很多时间才能覆盖整个建筑物。

二进制搜索法 (Binary Search Approach)

Let’s say you start from ground floor and got to the 50th floor with no stops. At the 50th floor, you stopped and got out of the lift and checked for the sign. The board sign said “No Pets”. This would mean that, until the 50th floor, there are definitely no pets.

假设您是从一楼开始,一直到50楼而已。 在50楼,您停下来,走出电梯,检查招牌。 板子上写着“No Pets” 。 这意味着直到50楼,绝对没有宠物。

So now knowing that you reduce your search space to the other half, which is floors 51–100. This means that with a single stop, you were able to cover half of the building knowing for sure that the first half doesn’t have any pets. That’s amazing!

因此,现在您知道将搜索空间减小到另一半,即第51-100层。 这意味着您只需停下来,就可以覆盖整个建筑物的一半,同时要确保前半部分没有宠物。 棒极了!

Moving on, you again divide your remaining set of floors into half and take the lift and go directly to the 75th floor. And you see a “Pets” sign board there. This means the floor where it started showing up must be between 50–75. You can keep following a similar approach of diving the remaining floors into half and checking until you find the first floor with the “Pets” sign board.

继续前进,您再次将剩余的楼层分成两半,乘坐电梯,直接进入第75层。 然后您会看到一个“Pets”标志牌。 这意味着开始显示的地板必须在50-75之间。 您可以继续采用类似的方法,将剩余的楼层分成两半,然后进行检查,直到找到带有“Pets”标志牌的第一层为止。

You see, every time you make a decision, you divide your search space into two halves and go ahead with one half of the search space. That’s how we narrow down our search. Since we always divide the search space in two and choose one over the other, that is why this type of search strategy is called a Binary search strategy.

您会看到,每次做出决定时,您都会将搜索空间分为两半,然后继续进行一半的搜索空间。 这就是我们缩小搜索范围的方式。 由于我们总是将搜索空间一分为二,然后选择一个,因此这就是为什么这种搜索策略称为Binary搜索策略。

Isn’t that way faster?

这样不是更快吗?

Let’s look into the algorithm for this.

让我们研究一下算法。

If you’ve been following along closely and have a grasp of the algorithm, you would have realized a hard and fast condition for the binary search algorithm to work. The condition is that the array needs to be sorted beforehand. In our example, the building floors were sorted from 1–100 and we could easily divide the search space in two.

如果您一直密切关注并掌握了该算法,那么您将认识到二进制搜索算法工作的艰巨条件。 条件是该数组需要事先排序。 在我们的示例中,建筑物楼层的分类范围为1–100,我们可以轻松地将搜索空间分为两部分。

Let’s look at an example array which is sorted and try and search for an element in it.

让我们看一个示例数组,该数组已排序并尝试在其中搜索元素。

In the above example, the element to be searched is 8. The given array is a sorted array in increasing order. Once we find the middle element (which is 5), we see that the element to be searched is greater than the current index element. Since the array is sorted in increasing order, 8 would lie on the right of the array and can never be on the left side.

在上面的示例中,要搜索的元素为8。给定数组是按升序排序的数组。 找到中间元素(为5)后,我们看到要搜索的元素大于当前索引元素。 由于数组是按升序排序的,因此8将位于数组的右侧,并且永远不能位于左侧。

So we ignore the elements to the left of 5 and continue our search with the remaining elements, eventually finding out 8.

因此,我们忽略5左边的元素,并继续搜索其余元素,最终找到8。

On the other hand, what if the array is not sorted? Even though we know the current element is 5 and we know we need to search for 8, we are not sure which direction is the right way to go. If we end up thinking the array is sorted and apply binary search and go to the right part, we will never find 8.

另一方面,如果数组未排序怎么办? 即使我们知道当前元素是5并且知道需要搜索8,我们也不确定哪个方向是正确的方向。 如果我们最终认为数组已排序并应用二进制搜索然后转到正确的部分,我们将永远找不到8。

So binary search essentially wants your array to be sorted.

因此,二进制搜索本质上是希望对数组进行排序。

That was the standard binary search algorithm that we just looked at. But, as the title of the article suggests, there is a twist in the tale!

那就是我们刚刚研究过的标准二进制搜索算法。 但是,正如文章标题所暗示的,这个故事有一个转折!

I am an avid competitive programmer, and there was an interesting variant of the binary search algorithm in the CodeChef May Long Challenge.

我是一个狂热的竞争程序员,在CodeChef May Long Challenge中有一个有趣的二进制搜索算法变体。

Essentially, the Chef wrote the classic binary search, assuming the input array would be sorted. All the other children in the class copied the code from him, as Chef is the best programmer in the class. His assumption could’ve cost the entire class their assignment marks, as the input array was not sorted beforehand.

本质上,Chef编写了经典的二进制搜索,并假设输入数组将被排序。 班上所有其他孩子都从他那里复制了代码,因为Chef是班上最好的程序员。 他的假设可能使整个类失去了分配标记,因为输入数组未事先排序。

The only thing the Chef can do is to preprocess the array by swapping some pair of numbers here and there so that the binary search procedure still returns the right index.

Chef唯一能做的就是通过在这里和那里交换一些数字对预处理数组,以便二进制搜索过程仍然返回正确的索引。

Note: The preprocessor above should ideally return the modified array for the binary search to work correctly. However, as the problem statement asks, we are just trying to determine the number of swaps needed for binary search to work correctly on the unsorted array given an input. The algorithm would also return a -1 if such a modification is not possible for the given array and element.

注意:理想情况下,上述预处理器应返回修改后的数组,以使二进制搜索正常工作。 但是,正如问题陈述所要求的,我们只是试图确定在给定输入的情况下,二进制搜索在未排序数组上正确运行所需的交换次数。 如果对于给定的数组和元素不可能进行这种修改,则该算法还将返回-1。

The idea here is very simple.

这里的想法很简单。

We need to understand two basic steps. I call them the TI-ME steps. Perhaps that’ll help you remember what we are doing here.

我们需要了解两个基本步骤。 我称它们为TI-ME步骤。 也许这可以帮助您记住我们在这里所做的事情。

a. Target Index: The index of the element to be searched for. We need to know this, since this index would help us drive the modifications. Because every time we modify any element, we need to sail towards this index and not away from it.

一个。 牛逼 ARGET ndex:要搜索的元素的索引。 我们需要知道这一点,因为该索引将帮助我们推动修改。 因为每次修改任何元素时,我们都需要朝着该索引航行而不是远离它。

b. Middle Element: If you look clearly in a binary search, it’s the middle element of the current search space which drives the next move. If this middle element takes us in the wrong direction, we need to replace with the appropriate element.

b。 中号 iddleè字元素:如果您在二进制搜索看清楚,它的驱动下移动当前的搜索空间的中间元素。 如果这个中间元素将我们引向错误的方向,则需要替换为适当的元素。

So, the whole idea here is that we swap all the middle elements which are wrongly placed.

因此,这里的整体思想是我们交换所有错误放置的中间元素。

The binary search algorithm (the value of the middle element with respect to the element to be searched, that is, X) can either take us towards the left half of the array or the right half. So, there are two possibilities for a wrongly placed middle element:

二进制搜索算法(相对于要搜索的元素而言,中间元素的值,即X)可以将我们带到数组的左半部分或右半部分。 因此,错误放置中间元素有两种可能性:

  1. The element to be searched was on the right of the middle element, but since Element[Mid] > Element[Target Index] , the binary search would have had to ignore the right half and move towards the left half. OR

    要搜索的元素在中间元素的右侧,但是由于Element[Mid] > Element[Target Ind ex],因此二进制搜索将不得不忽略右半部分而向左半部分移动。 要么

  2. The element to be searched was on the left of the middle element, but since Element[Mid] < Element[Target Index] , the binary search would have had to ignore the left half and move towards the right half.

    要搜索的元素在中间元素的左侧,但是由于Element[Mid] < Element[Target Ind ex],因此二进制搜索将不得不忽略左半部分而向右半部分移动。

Therefore, if a middle element is wrongly placed such that a number X was needed in its place where X < Element[Target Index] , then we maintain a counter for that and call it count_low_needed .

因此,如果错误地放置了一个中间元素,使得在X < Element[Target Ind ex]的位置需要数字X ,则我们为此维护一个计数器并将it count_low_nee ded。

Similarly, if a middle element is wrongly placed such that a number X was needed in its place where X > Element[Target Index] , then we maintain a counter for that and call it count_high_needed .

同样,如果错误地放置了一个中间元素,使得在X > Element[Target Ind ex]的位置需要数字X ,则我们为此维护一个计数器,并将it count_high_nee ded。

Also, if we simply run the binary search algorithm over the given array while searching for numbers, there would be some numbers that would be correctly placed. These would be the middle elements that drove the binary search in correct directions corresponding to the given element X (the element to be searched). These numbers cannot be a part of the swapping, because they are rightly positioned with respect to X .

另外,如果我们在搜索数字时仅在给定的数组上运行二进制搜索算法,那么将会正确放置一些数字。 这些将是在与给定元素X (要搜索的元素)相对应的正确方向上推动二进制搜索的中间元素。 这些数字不能作为交换的一部分,因为它们相对于X位置正确。

Let’s look at the pseudo code for this algorithm first and then go through an example.

让我们先看一下该算法的伪代码,然后再看一个例子。

function can_preprocess(arr, X){     low = 0     high= 0
while X is not found {          mid = (low + high) / 2          if arr[mid] == X {             break                     }
correctly_placed_low = 0          correctly_placed_high = 0          count_low_needed = 0          count_high_needed = 0
if `mid` suggests we should go right for X {               if X is actually on the right {                   correctly_placed_low ++               }               else {                   count_low_needed ++               }          } else {               if X is actually on the left {                  correctly_placed_high ++               }                else {                  count_high_needed ++               }          }
modify low and high according to           where `X` actually is with respect to `mid`
}
// Total smaller numbers available for swapping     TSM = sorted_index[X] - correctly_placed_low
// Total Larger numbers available for swapping     TLM = (N - sorted_index[X]) - correctly_placed_high
if count_low_needed > TSM or count_high_needed > TLM {          return -1     }
return max(count_low_needed, count_high_needed)

NOTE: The problem statement fixes the input array for us and repeatedly passes values to be searched in the input array. So, we can iterate once over the original array to know the actual location of the element to be searched (create a dictionary, essentially).

注意:问题声明为我们修复了输入数组,并反复传递要在输入数组中搜索的值。 因此,我们可以遍历原始数组一次,以了解要搜索的元素的实际位置(本质上是创建字典)。

Also, we need sorted_index[X] to tell us how many values are lesser than or greater than the element X in our array. We can sort the array and create another dictionary storing location of each element in the sorted array.

另外,我们需要sorted_index[X]告诉我们有多少个值小于或大于数组中的元素X 我们可以对数组进行排序,并创建另一个字典来存储排序后的数组中每个元素的位置。

Let’s go through the steps of the proposed algorithm while dry running an example.

让我们在尝试运行示例的同时浏览所提出算法的步骤。

  1. Given an unsorted array, you need to search for X = 4 .

    给定一个未排序的数组,您需要搜索X = 4

    Hence our target index is 7.

    因此,我们的目标指数是7。

2. Mid element index < Target Index, so we need to maneuver our search to the right half. But Element[Mid] > Element[Target Index], hence count_low_needed = 1

2.中元素索引<目标索引,因此我们需要将搜索调整到右半部分。 但是ut Element[Mid] > Element[Target索引], hence count_low_need ed = 1

3. Mid element index < Target Index, so we still need to maneuver our search to the right half. Once again, Element[Mid] > Element[Target Index], hence count_low_needed = 2

3.中元素索引<目标索引,因此我们仍然需要将搜索调整到右半部分。 再次n, Element[Mid] > Element[Target索引], hence count_low_need ed = 2

4. The total number of swaps needed for binary search to return the correct index here would be two swaps with elements lower than 4. We have smaller numbers 1, 3 or 2 for swapping available, so we can successfully do the swapping for this array so that binary search correctly finds out 4 .

4.返回此处正确索引的二进制搜索所需的交换总数将是元素小于4的两次交换。我们可以使用较小的数字1, 3 or 2进行交换,因此我们可以成功地对该数组进行交换这样二进制搜索就可以正确找出4

Below is the Python code for the given problem. Every step is explained in the comments.

以下是给定问题的Python代码。 注释中说明了每个步骤。

The time complexity of this Twisted Binary Search algorithm is still O(nlogn) .

这种扭曲二进制搜索算法的时间复杂度仍为O(nlogn)

I hope you were able to grasp the inner workings of the binary search algorithm and had fun while going through this interesting problem as well. If you found this post useful, spread the love and share as much as possible. ?

我希望您能够掌握二进制搜索算法的内部工作原理,并且在经历这个有趣的问题时也很开心。 如果您发现此帖子有用,请传播爱心并尽可能多地分享。 ?

翻译自: https://www.freecodecamp.org/news/a-twisted-tale-of-binary-search-49f5ac01e83d/

二进制搜索算法

二进制搜索算法_二进制搜索的一个扭曲故事相关推荐

  1. 二进制搜索算法_使用安全摄像机镜头解释二进制搜索算法

    二进制搜索算法 by Julia Geist Julia·盖斯特(Julia Geist) 使用安全摄像机镜头解释二进制搜索算法 (Binary Search Algorithms explained ...

  2. 二进制搜索树_二进制搜索树数据结构举例说明

    二进制搜索树 A tree is a data structure composed of nodes that has the following characteristics: 树是由具有以下特 ...

  3. 二进制树形搜索算法_二进制搜索

    二进制树形搜索算法 二进制搜索用于在 值的排序列表 . 它选择排序值数组中的中间元素,并将其与目标值进行比较: 这就是我们在数组中寻找的关键. 如果它小于目标值,则在中间元素之后搜索,直到数组末尾. ...

  4. java 删除二进制内容_二进制搜索树节点删除不删除替换Java

    我试图从二进制搜索树中删除节点.除了一个特定的情况,我可以成功删除树上的任何其他节点.如果目标节点有2个子节点,并且左子节点具有右子树,我可以找到正确的替换节点并将值切换到目标节点,但是永远不会删除替 ...

  5. mysql二进制格式_二进制格式安装 MySQL

    二进制格式安装 MySQL 什么是通用二进制格式? 已经编译进行过编译的软件包, 下载到本机直接解压到特定的目录下就可以使用的格式. 1. 查询本地是否安装 mysql 数据库相关的软件包 (卸载之) ...

  6. java 删除二进制内容_二进制搜索树节点删除

    我正在实现从二叉搜索树中删除节点的功能 . 该功能的原型已设置,我无法更改它,这是一项学校作业 . 我的代码: typedef struct tBSTNode { char Key; struct t ...

  7. c++将十进制转换为二进制 小数_二进制、八进制、十六进制与转换

    将二进制.八进制.十六进制转换为十进制 二进制.八进制和十六进制向十进制转换都是非常容易的,就是"按权相加". 所谓"权",也即"位权". ...

  8. JavaScript中的二进制搜索算法

    在本文中,我将比较线性搜索和二进制搜索算法. 您将看到每种算法的伪代码,以及示例和实现每种方法的逐步指南. 介绍 作为程序员,您想找到问题的最佳解决方案,以使您的代码不仅正确而且高效. 选择次优算法可 ...

  9. java实现递归算法_如何在Java中实现二进制搜索算法而无需递归

    java实现递归算法 by javinpaul 由javinpaul 流行的二进制搜索算法的迭代实现,用于在排序数组中查找元素. (An Iterative implementation of the ...

最新文章

  1. linux下修改网卡接口名称
  2. python布尔系列_python数据分析类库系列-Numpy之布尔型索引
  3. 线程可以kill吗_我是一个线程(转)
  4. 一个奇怪的sql异常
  5. 开发app用户协议_家电商城APP开发,方便用户选购家电商品
  6. mysql 搭建日志服务器_一、架构01-搭建日志服务器Rsyslog
  7. Python 爬虫利器三之 Xpath 语法与 lxml 库的用法
  8. linux中c语言生日快乐_生日快乐,Linux:27岁
  9. DAG最长路问题 hdu-1224
  10. The system is running in low-graphics mode
  11. Vmware使用net模式共享虚拟机linux IP
  12. Emacs学习笔记(8): 使用emacs浏览网页
  13. openpyxl 列 插入_openpyxl3.0.3 中文手册--插入删除行和列、移动单元格
  14. SQL,修改表列明错误,不允许保存更改,阻止保存要求重新创建表的更改
  15. github客户端进行token认证
  16. mac如何把html转成word,Pages怎么保存为word格式 pages保存格式教程
  17. 1438oracle,一次ora-01438错误的处理
  18. ACCESS实例2 资料管理2——窗体创建方法
  19. 在MarkDown中插入本地图片
  20. Windows Server 2008 定时任务卡住了不执行

热门文章

  1. 大牛手把手教你!2021Java最新大厂面试真题
  2. 灵魂拷问!一起刷完了这份1307页的安卓面试宝典吧,不吃透都对不起自己
  3. matlab dwt 多层分解,利用matlab对图片进行多层小波分解 会的加QQ511607771 加过作图之后积分加倍送...
  4. Codeforces 1144D Deduction Queries 并查集
  5. dubbo负载均衡策略和集群容错策略
  6. array_combine()
  7. Shell编程 之 for 循环
  8. 200道物理学难题——038蚱蜢跃树
  9. [转载]PSCAD调用MATLAB/SIMULINK之接口元件设计
  10. 16.U-boot的工作流程分析-2440