From 821a9b75781acf803563aea1c9ddef161a3aae13 Mon Sep 17 00:00:00 2001 From: Wen Chuan Lee Date: Tue, 22 Jun 2021 11:22:13 -0700 Subject: [PATCH] Improve translation for binary search --- think_like_computer/DetailedBinarySearch.md | 172 +++++++++++--------- 1 file changed, 95 insertions(+), 77 deletions(-) diff --git a/think_like_computer/DetailedBinarySearch.md b/think_like_computer/DetailedBinarySearch.md index 6309372973..d079844dd3 100644 --- a/think_like_computer/DetailedBinarySearch.md +++ b/think_like_computer/DetailedBinarySearch.md @@ -1,24 +1,20 @@ # Detailed Binary Search -**Translator: [Kevin](https://github.com/Kevin-free)** - -**Author: [labuladong](https://github.com/labuladong)** +First, let me tell you a joke to cheer things up: -First, let me tell you a joke cheerful: - -One day Adong went to the library and borrowed N books. When he went out of the library, the alarm went off, so the security guard stopped Adong to check which books were not registered for loan. ADong is going to go through each book under the alarm to find the book that caused the alarm, but the security guard's disdainful look: Can't you even do a binary search? Then the security divided the books into two piles, let the first pile pass the alarm, the alarm sounded; then divided the pile into two piles ... Finally, after checking logN times, the security successfully found the one that caused the alarm The book showed a smug and ridiculous smile. So Adong left with the remaining books. +One day Adong went to the library and borrowed N books. When he went out of the library, the alarm went off, so the security guard stopped Adong to check which books were not correctly checked out for loan. ADong is going to go through each book under the alarm to find the book that caused the alarm, but the security guard's gave a disdainful look: Don't you know how to do binary search? Then the security divided the books into two piles, let the first pile pass through the alarm, the alarm sounded; then divided the pile into two piles ... Finally, after checking `logN` times, the security successfully found the one that caused the alarm, displaying his satisfied and smug smile. Only then did Adong leave with the remaining books. Since then, the library has lost N-1 books. -Binary search is not easy. The mogul Knuth (the one who invented the KMP algorithm) said that binary search: **Although the basic idea of binary search is comparatively straightforward, the details can be surprisingly tricky...** Many people like to talk about integer overflow bugs, but the real pit of binary search is not the detail problem at all, but whether to add one to or subtract one from `mid`, whether to use` <= `in while `<`. +Binary search is not easy. Donald Knuth (the one who invented the KMP algorithm) said this about binary search: **Although the basic idea of binary search is comparatively straightforward, the devil is in the details...** Many people like to talk about integer overflow bugs, but the real trap of binary search is not just in the details, but whether to add one to or subtract one from `mid`, whether to use` <= ` or `<` in the `while` loop. -If you don't understand these details correctly, writing dichotomy is definitely metaphysical programming, and if there is a bug, you can only rely on bodhisattva to bless it. **I deliberately wrote a poem to celebrate the algorithm, summarize the main content of this article, and suggest to save:** +If you don't understand these details correctly, writing binary search is definitely akin to metaphysics, whether there'll be a bug would be reliant on Buddha's blessings. **I deliberately wrote a poem to celebrate the algorithm, summarize the main content of this article, and I suggest you save it:** `//FIXME: Poem isn't a true translation, but you can skip this given it's not critical for this article.` ![](../pictures/DetailedBinarySearch/verse.jpg) -This article explores some of the most commonly used binary search scenarios: finding a number, finding the left boundary, and finding the right boundary. Moreover, we are going to go into details, such as whether the inequality sign should be accompanied by an equal sign, whether mid should be increased by one, and so on. Analyze the differences in these details and the reasons for these differences to ensure that you can write the correct binary search algorithm flexibly and accurately. +This article explores some of the most commonly used binary search scenarios: finding a number, finding the left boundary, and finding the right boundary. Moreover, we are going to go into details, such as whether the inequality sign should be accompanied by an equal sign, whether `mid` should be increased by one, and so on. Analyze the differences in these details and the reasons for these differences to ensure that you can write the correct binary search algorithm flexibly and accurately. -### Zero, binary search framework +### 0. Binary Search Framework ```java int binarySearch(int[] nums, int target) { @@ -38,14 +34,14 @@ int binarySearch(int[] nums, int target) { } ``` -**A technique for analyzing binary search is: do not appear else, but write everything clearly with else if, so that all details can be clearly displayed**. This article will use else if to make it clear, and readers can simplify it after understanding. +**A technique for analyzing binary search is: do not have an `else` clause, but write everything clearly with `else if`, so that all details can be clearly displayed**. This article will use `else if` to make it clear, and readers can simplify it after understanding. The section marked with `...`, is the place where details may occur. When you see a binary search code, pay attention to these places first. The following sections use examples to analyze what changes can be made in these places. -In addition, it is necessary to prevent overflow when calculating mid. `left + (right-left) / 2` is the same as` (left + right) / 2` in the code, but it effectively prevents `left` and` right`. Too large a direct addition causes an overflow. +In addition, it is necessary to prevent integer overflow when calculating mid. `left + (right-left) / 2` is the same as` (left + right) / 2` in the code, but it effectively prevents `left` and` right`. Too large a direct addition causes an overflow. -### First, find a number (basic binary search) +### 1. Find a number (basic binary search) This scenario is the simplest and certainly the most familiar to everyone, that is, searching for a number, if it exists, returns its index, otherwise it returns -1. @@ -67,13 +63,13 @@ int binarySearch(int[] nums, int target) { } ``` -**1. Why is <= instead of < in the condition of the while loop?** +**1. Why is it `<=` instead of `<` in the while loop?** -Answer: Because the initial assignment of `right` is` nums.length-1`, which is the index of the last element, not `nums.length`. +Answer: Because the initial assignment of `right` is `nums.length - 1`, which is the index of the last element, not `nums.length`. -These two may appear in binary search with different functions. The difference is that the former is equivalent to the both closed interval `[left, right]`, and the latter is equivalent to the left closed right opening interval `[left, right)`, because An index size of `nums.length` is out of bounds. +These two may appear in binary search with different functions. The difference is that the former is equivalent to the both closed interval `[left, right]`, and the latter is equivalent to the left closed right opening interval `[left, right)`, because an index size of `nums.length` is out of bounds. -In our algorithm, we use the interval where `[left, right]`is closed at both ends. **This interval is actually the interval for each search**. +In our algorithm, we use the interval where `[left, right]` is closed at both ends. **This interval is actually the interval for each search**. When should you stop searching? Of course, you can terminate when the target value is found: @@ -82,13 +78,13 @@ When should you stop searching? Of course, you can terminate when the target val return mid; ``` -But if not found, you need to terminate the while loop and return -1. When should the while loop terminate? **It should be terminated when the search interval is empty**, which means that if you don't have to find it, it means you haven't found it. +But if not found, you need to terminate the while loop and return -1. When should the while loop terminate? **It should be terminated when the search interval is empty**, which means that if you've run out of candidates to search, which means you haven't found it. The termination condition of `while (left <= right)` is `left == right + 1`, written in the form of an interval is` [right + 1, right] `, or with a specific number in it `[3, 2] `, It can be seen that **the interval is empty at this time**, because no number is greater than or equal to 3 and less than or equal to 2. So the termination of the while loop is correct at this time, just return -1. -The termination condition of `while (left = nums.length || nums[left] != target) return -1; return left; @@ -445,7 +455,7 @@ int right_bound(int[] nums, int target) { left = mid + 1; } } - // Check whether right border out of bounds lastly + // Finally, check whether right border out of bounds if (right < 0 || nums[right] != target) return -1; return right; @@ -456,12 +466,20 @@ If you can understand the above, then congratulations, the details of the binary Through this article, you learned: -1. When analyzing the binary search code, do not appear else, expand all into else if for easy understanding. +1. When analyzing the binary search code, do not write `else`, expand all into `else if` statements for easy understanding. + +2. Pay attention to the termination conditions of "search interval" and `while`-loop termination conditions. If there are missing elements, remember to check at the end of the algoritm. -2. Pay attention to the termination conditions of "search interval" and while. If there are missing elements, remember to check at the end. +3. If you need to define the left-closed and right-open "search interval" to search the left and right boundaries, you only need to modify it when `nums [mid] == target`, and you need to subtract one when searching the right side. -3. If you need to define the left and right "search interval" to search the left and right boundaries, you only need to modify it when `nums [mid] == target`, and you need to subtract one when searching the right side. +4. If the "search interval" is unified to be closed at both ends, it is easy to remember, as long as you slightly change the code and return logic at the condition of `nums [mid] == target`, **it is recommended to note down this binary search template in your notebooks**. -4. If the "search interval" is unified to be closed at both ends, it is easy to remember, as long as you slightly change the code and return logic at the condition of `nums [mid] == target`, **it is recommended to take a small book As a binary search template**. +Lol, all binary search questions should be no match for this article! +[Previous: The Framework for Backtracking Algorithm](think_like_computer/DetailsaboutBacktracking.md) +[Next: The Sliding Window Technique](think_like_computer/SlidingWindowTechnique.md) +[Table of Contents](../README.md#table-of-contents) + +**Translator: [Kevin](https://github.com/Kevin-free)** +**Author: [labuladong](https://github.com/labuladong)** \ No newline at end of file