当前位置: 首页 > news >正文

【牛客刷题-算法】NC32 求平方根 (又是辛苦debug的一天)

个人主页:清风莫追
系列专栏:牛客刷题——数据结构与算法
🔥 该专栏作为刷题笔记,持续更新中。
推荐一款面试、刷题神器牛客网:👉点击加入刷题大军👈

文章目录

  • 1.题目描述
  • 2.算法设计思路
    • 1)初稿
    • 2)bug
  • 3.算法实现
  • 4.运行结果
  • 结束语:


1.题目描述

描述

实现函数 int sqrt(int x).

计算并返回 x 的平方根(向下取整)

数据范围 0 < = x < 2 31 − 1 0<=x<2^{31}-1 0<=x<2311

要求:空间复杂度 O ( 1 ) O(1) O(1),时间复杂度 O ( l o g x ) O(logx) O(logx)

2.算法设计思路

1)初稿

关键信息:所求x的平方根是一个向下取整的整数。

总体思路:二分搜索
1.二分搜索,首先要有一个初始区间,例如 [ 1 , x ] [1,x] [1,x]
2.搜索时每次取区间的中点值mid,看是否为x的平方根。
3.若mid就为x的平方根,则返回mid;否则,继续对mid左右两个区间进行二分搜索。

细节
1.判断一个数mid是否为x的平方根:mid的平方等于x;mid的平方比x小,且mid+1的平方比x大。(注意是向下取整)
2.对一个区间停止搜索的条件:搜到区间只剩下一个元素
3.当区间恰好剩两个元素而不能分为三部分:分别判断这两个元素是否为x的平方根

2)bug

在按照最初的算法设计思路编写完代码后,我并没有成功通过

第一个问题:判断平方根
在判断一个数t是否为x的平方根时,我使用t * t <= x && (t+1)*(t+1) >= x的方式,这样就存在一个漏洞,例如当t为2且x为9时,该表达式将返回true

第二个问题:数据范围
x是int,但是x的平方就不是了,会溢出。干脆就不平方了,就比较x / t 与 t的大小。

第三个问题:0作为除数
从乘法改到除法,就要小心0了。

第四个问题:我真的二分了吗?
就在我以为自己终于要过了的时候,报了个超时的错误。本来在二分搜索中,每次搜索后剩余区间都会缩小为原来的一半,而我没有写停止另一半搜索的判断,倒在了x=21亿这个测试数据上。

添加二分时丢掉一半区间的判断:如果一个区间的最大(小)值都比x的平方根小(大),就没必要继续搜索该区间了。

if((e+1) < x / (e+1) || (f > 1 && (f-1) > x / (f-1)))
            return;

小结
写bug改bug,bug套bug,好在“神龟虽寿,犹有竟时”,修修补补终于还是过了这一关。

3.算法实现

注:这里并不是完整代码,而只是核心代码的模式

成功通过的C++代码:

class Solution {
  public:
    //判断xsqrt是否为x的平方根
    bool is_sqrt(int x, int xsqrt) {
        int t = x / xsqrt;
        int t2 = x / (xsqrt + 1);
        if (t >= xsqrt && t2 < (xsqrt + 1)) {
            return true;
        }
        return false;
    }
    //在【1,x】的区间中采用二分搜索x的平方根
    void find(int x, int f, int e, int & result) {
        if((e+1) < x / (e+1) || (f > 1 && (f-1) > x / (f-1)))
            return;
        if (e - f == 0) {
            if (is_sqrt(x, f)) {
                result = f;
            }
            return;
        }
        if (e - f == 1) {
            if (is_sqrt(x, f)) {
                result = f;
            }
            if (is_sqrt(x, e)) {
                result = e;
            }
            return;
        } 

        int mid = (f + e) / 2;
        if(is_sqrt(x, mid)){
            result = mid;
            return;
        }
        find(x, f, mid - 1, result);
        find(x, mid + 1, e, result);
    }
    //返回x的平方根
    int sqrt(int x ) {
        // write code here
        if(x == 0)
            return 0;
        int result = 0;
        find(x, 1, x, result);
        return result;
    }
};

4.运行结果

成功通过!

在这里插入图片描述


结束语:

今天的分享就到这里啦,快来加入刷题大军叭!
👉点击开始刷题学习👈

在这里插入图片描述


感谢阅读

CSDN话题挑战赛第2期
参赛话题:学习笔记

相关文章:

  • Verilog学习笔记
  • SAP PI PO 接口常见问题处理:应用程序使用内容计划
  • 临床预测之logictic回归 1-2
  • 计算机学院第一周语法组及算法组作业
  • 【Pandas 数据分析 1】快速入门
  • Python中计算程序的运行时间——timeit模块
  • 第十三届蓝桥杯JavaB组省赛——最大子矩阵 (AC)
  • 【CMake】第2篇 CMake构建.h与.cpp文件
  • Kmeans
  • 【C++】C++11的那些新特性
  • 【数据结构 | 入门】线性表与链表 (问题引入实现算法优化)
  • vmware虚拟机中的archlinux无法播放声间的解决办法
  • 深度学习常用的backbone有哪些
  • 君正X2000/X1600主控CPU方案有哪些场景?行业迈向人机交互智能时代来啦!
  • c++类和对象万字详解
  • [原]深入对比数据科学工具箱:Python和R 非结构化数据的结构化
  • 「前端早读君006」移动开发必备:那些玩转H5的小技巧
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • 【附node操作实例】redis简明入门系列—字符串类型
  • 【前端学习】-粗谈选择器
  • electron原来这么简单----打包你的react、VUE桌面应用程序
  • JavaScript对象详解
  • JavaScript函数式编程(一)
  • JavaSE小实践1:Java爬取斗图网站的所有表情包
  • node-glob通配符
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • vue.js框架原理浅析
  • 发布国内首个无服务器容器服务,运维效率从未如此高效
  • 浮动相关
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 容器服务kubernetes弹性伸缩高级用法
  • 以太坊客户端Geth命令参数详解
  • 摩拜创始人胡玮炜也彻底离开了,共享单车行业还有未来吗? ...
  • ​io --- 处理流的核心工具​
  • #经典论文 异质山坡的物理模型 2 有效导水率
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • (52)只出现一次的数字III
  • (C语言)编写程序将一个4×4的数组进行顺时针旋转90度后输出。
  • (笔试题)合法字符串
  • (二十四)Flask之flask-session组件
  • (四) 虚拟摄像头vivi体验
  • (转)Oracle存储过程编写经验和优化措施
  • (转)shell调试方法
  • (转)VC++中ondraw在什么时候调用的
  • ... fatal error LINK1120:1个无法解析的外部命令 的解决办法
  • .NET Remoting学习笔记(三)信道
  • .NET 设计一套高性能的弱事件机制
  • /使用匿名内部类来复写Handler当中的handlerMessage()方法
  • [Android]How to use FFmpeg to decode Android f...
  • [Asp.net mvc]国际化
  • [BUG]Datax写入数据到psql报不能序列化特殊字符
  • [BZOJ1877][SDOI2009]晨跑[最大流+费用流]
  • [Bzoj4722]由乃(线段树好题)(倍增处理模数小快速幂)
  • [CISCN2019 华东北赛区]Web2
  • [EWS]查找 文件夹