C++ 刷题坑: 二分查找也没有那么容易写出来


最近在刷题, 刷了一道比较简单的二分搜索, 但是却让我刷了好几次才过(果真是很久没刷 能力立马下降许多)

题意就是 不允许使用 sqrt 或者 pow 之类的函数来判断一个整数是否是平方数. 比如 4, 16, 64, 25 就是平方数而 3, 7, 11 不是.

很容易想到可以用二分搜索来解决, 算法复杂度是 O(log n), 答案如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
typedef unsigned long long INT64;
 
class Solution {
public:
    /**
     * @param num: 一个正整数
     * @return: num 是否是个完全平方数
     */
    bool isPerfectSquare(int num) {
        int low = 1;
        int high = num;
        while (low <= high) {
            int mid = low + (high - low) / 2;
            auto midmid = (INT64)mid * mid;
            if (midmid == num) {
                return true;
            }
            if (num < midmid) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return false;
    }
};
typedef unsigned long long INT64;

class Solution {
public:
    /**
     * @param num: 一个正整数
     * @return: num 是否是个完全平方数
     */
    bool isPerfectSquare(int num) {
        int low = 1;
        int high = num;
        while (low <= high) {
            int mid = low + (high - low) / 2;
            auto midmid = (INT64)mid * mid;
            if (midmid == num) {
                return true;
            }
            if (num < midmid) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return false;
    }
};

用C++来写有几个坑:

  • 中间平方 midmid = mid * mid 的值很可能超过了32位整数的范围, 所以需要64位整型.
  • mid * mid 表达式结果是32位值, 除非你强制转换成64位.
  • (low + high) / 2 取中间的方法也很可能会溢出, 而 low + (high – low) / 2则安全.
  • 正确的边界判断while (low <= high) 而不是while (low < high), 很多人在白板上写二分查找很容易犯得错.
  • 每次缩小搜索范围的边界都需要 加减一: high = mid – 1 和 low = mid + 1

看似很简单的二分搜索, 却不容易一次性写对.

英文: The C++ Pitfalls of Checking Perfect Square using Binary Search

刷题:程序员的基本技能

GD Star Rating
loading...
本文一共 256 个汉字, 你数一下对不对.
C++ 刷题坑: 二分查找也没有那么容易写出来. (AMP 移动加速版本)
上一篇: 糖尿病和幽門螺桿菌
下一篇: CloudFlare 互联网峰会

扫描二维码,分享本文到微信朋友圈
4e8687d4c46e3351ae8e20ecb8a03b83 C++ 刷题坑: 二分查找也没有那么容易写出来 ACM题解 程序设计

2 条评论

评论