1. x 的平方根

    实现 int sqrt(int x) 函数。

    计算并返回 x 的平方根,其中 x 是非负整数。

    由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。

    示例 1:

    输入: 4
    输出: 2

    示例 2:

    输入: 8
    输出: 2
    说明: 8 的平方根是 2.82842…,
    由于返回类型是整数,小数部分将被舍去。

    第一种写法:按照数学公式做二分范围限制,理解起来比较困难

    1. class Solution {
    2. public int mySqrt(int x) {
    3. /**
    4. 思路1:暴力法
    5. (1)遍历1 - x的数字,求平方与x大小做对比
    6. (2)等于的时候,即为当前值,大于的时候,即为上一个值
    7. 思路2:二分法
    8. (1)1-x这个范围内,对1-x做二分查找,如果一个数的平方大于x,说明这个数一定不是x的平方根
    9. (2)所以需要找到第一个平方小于等于x的数字
    10. (3)但是二分法有可能会出现找到第一个小于之后,实际结果在范围之外,所以当出现小于等于的时候,
    11. 右移左指针,再此执行二分操作
    12. (4)当l=r的时候即为找到了结果
    13. */
    14. if(x == 0 ){
    15. return 0;
    16. }
    17. if(x == 1){
    18. return 1;
    19. }
    20. int left = 1;
    21. int right = x / 2;
    22. // 在区间 [left..right] 查找目标元素
    23. while (left < right) {
    24. int mid = left + (right - left + 1) / 2;
    25. // 注意:这里为了避免乘法溢出,改用除法
    26. if (mid > x / mid) {
    27. // 下一轮搜索区间是 [left..mid - 1]
    28. right = mid - 1;
    29. } else {
    30. // 下一轮搜索区间是 [mid..right]
    31. left = mid;
    32. }
    33. }
    34. return left;
    35. }
    36. }

    第二种写法:正常思路的二分法,按照1……x这个范围进行二分

    1. class Solution {
    2. // 上面的写法不是很好理解,再来一种新写法
    3. // 第二种写法
    4. public int mySqrt(int x){
    5. if(x == 0 ){
    6. return 0;
    7. }
    8. int left=1;
    9. int right = x,ans = -1;
    10. // 这里小于等于,是考虑x=1这种场景
    11. while(left <= right){
    12. // 正常来说这么写没问题,但是如果x是byte类型,那么范围是125 - 127,如果相加除以2会出现溢出
    13. // int mid = (left + right) / 2;
    14. // 因此换成下列写法
    15. int mid = left + (right - left)/2;
    16. // 除法代替乘法,同样是为了防止溢出
    17. // 当mid大于x/mid说明,mid比平方根大
    18. if(mid > x / mid){
    19. right = mid-1;
    20. }else{
    21. left = mid+1;
    22. ans = mid;
    23. }
    24. }
    25. return ans;
    26. }
    27. }