2

Hello everyone, my name is lucifer. Today I will share with you the debug killers that are commonly used in my daily work!

binary code

My ultimate solution is binary code when I find a bug that is hard to understand and find.

For example, first delete half of the code in file a (approximately), and then test whether the problem is still there.

  • If the problem is gone, then we have found the problematic code.
  • If the problem is still there, then we continue to use the same method, continue to delete half of the code in file a (approximately), and then test whether the problem is still there.
  • Repeat the above steps until you find the offending code

This method is very useful when I have no thoughts for a while or to help others locate the problem. Since the time complexity of this approach is roughly logn, we can roughly locate the problem code in just a few short times. Similarly, we can also do bisection in multiple files at the same time.

Two point submission

More often, we find a bug between releases. And there are several commits between these two releases, and there are still quite a few (dozens or even hundreds of them).

We can also use a similar approach.

  • First switch to the intermediate commit x between the two releases (that is, to minimize the distance difference between commit x and the two releases).
In fact this minimum distance difference is either 0 or 1
  • Verify that the problem exists. If it doesn't exist, we can't be sure it's the problem with this commit, so we might as well mark the current commit c as good first. If it exists, you might as well mark the current commit c as bad.

  • After the above markup, we can find the commit that presented the earliest bad, and the most critical is that the complexity is logn, where n is the total number of commits we need to verify. Obviously, this workload is much faster than checking commits one by one.
Don't understand why? We'll talk about that later.

Binary Search in Git

The developers of git also thought of this, so they provide the bisect command to help us do the above.

Problem finding with bisect mainly relies on the following three commands:

  1. git bisect start

To start a lookup, start can be followed by good and bad commit points:

git bisect start [rev bad] [rev good]

If you don't add good and bad commit points, then git will wait until we use the good and bad commands to specify the corresponding commit points to start searching

  1. git bisect good

It is correct to mark a commit point. You can add rev to specify a specific commit point. If not, the current commit point will be marked by default.

  1. git bisect bad

It is used to mark a commit point that contains problems. If bad, you can add rev to specify a specific commit point. If not, the current commit point will be marked by default.

The principle behind

Let's fill the hole ahead. Why after such a tag, we can find the first commit with the problem (tag bad)? And the time complexity is $O(logn)$.

There is a principle of force buckle, let's talk about it directly.

Title address (278. The first wrong version)

https://leetcode-cn.com/problems/first-bad-version/

Topic description

你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。

假设你有 n 个版本 [1, 2, ..., n],你想找出导致之后所有版本出错的第一个错误的版本。

你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。

 

示例 1:

输入:n = 5, bad = 4
输出:4
解释:
调用 isBadVersion(3) -> false
调用 isBadVersion(5) -> true
调用 isBadVersion(4) -> true
所以,4 是第一个错误的版本。


示例 2:

输入:n = 1, bad = 1
输出:1


 

提示:

1 <= bad <= n <= 231 - 1

ideas

It can be seen that the process is the same as our description above. And our goal is to find the first commit that fails.

To be clear:

  • If a version x is good, then all commits between [1, x] must be good, so the version to be checked becomes [x+1,n]
  • If a version x is bad, then all commits between [x, n] must be bad. Since we are looking for the first problematic version, the version to be detected becomes [1,x-1]

So no matter if the version we detect is good or bad, we can halve the number of versions to detect, which means we can find the first problematic version in $logn$ times.

If you have read my bisection topic, you should know that this is the leftmost bisection of that I summarized .

code

  • Language support: Python3

Python3 Code:


class Solution:
    def firstBadVersion(self, n):
        l, r = 1, n
        while l <= r:
            mid = (l + r) // 2
            if isBadVersion(mid):
                # 收缩
                r = mid - 1
            else:
                l = mid + 1
        return l

Complexity Analysis

  • Time complexity: $O(logn)$
  • Space complexity: $O(1)$

Summarize

Dichotomous Dafa is still widely used in daily work, and finding bugs by dichotomy is one of the very practical skills. The simplest binary search for bugs can be done by deleting the contents of the file. And if there are many files, it is very inconvenient. At this time, we can use binary submission to complete.

The principle is actually very simple, that is, a simple leftmost bisection. If you are not familiar with this, it is strongly recommended to read the two-part topic mentioned in the article. The 20,000-word summary will definitely give you something to gain.


lucifer
5.3k 声望4.6k 粉丝