《程序员面试金典(第6版)面试题 16.09. 运算

news2024/10/7 19:18:32

题目描述

请实现整数数字的乘法、减法和除法运算,运算结果均为整数数字,程序中只允许使用加法运算符和逻辑运算符,允许程序中出现正负常数,不允许使用位运算。

你的实现应该支持如下操作:

  • Operations() 构造函数
  • minus(a, b) 减法,返回a - b
  • multiply(a, b) 乘法,返回a * b
  • divide(a, b) 除法,返回a / b

示例:

Operations operations = new Operations();
operations.minus(1, 2); //返回-1
operations.multiply(3, 4); //返回12
operations.divide(5, -2); //返回-2

提示:

  • 你可以假设函数输入一定是有效的,例如不会出现除法分母为0的情况
  • 单个用例的函数调用次数不会超过1000次

解题思路与代码

  • 这道题属实是一道中等难度的题。需要你有一定的思考量,才可以做出来。

  • 题目的要求是,不允许我们使用位运算符,除了 + 法以外的算术运算符,去实现两个数之间的减法,乘法,除法函数。

  • 也就是说,我们可以使用 + 法运算符,关系运算符(==, <= , >=, < , >)还有逻辑运算符 ( ! , && , ||)去实现这些函数。

  • 这道题建议大家不要抖机灵,使用各种没有意义的库函数来简便运算。还有这道题也不要去使用vector这种数据结构。因为,vector的模板类在实现时涉及到位运算符和减法运算符的

接下来,其实我们就要思考一个问题。乘法,除法的本质是什么?

  • 那其实是不是就是加法(乘法的本质是加法)与减法(除法的本质是减法)呢?
  • 那也就是说,要实现除法函数,首先得实现减法函数。

那我们,在来思考一个问题,减法的本质是什么?

  • 那是不是加上一个相反数呢?
  • 所以要实现减法函数,首先我们还需要去实现一个取反函数。

其实这道题还有一个隐藏的条件,那就是提示:单个用例的函数调用次数不会超过1000次

  • 也就是说,这道题,出题人不想你太容易去解决这个问题。问你如何优化流程,也就是缩短时间复杂度。
  • 假如说我们要用累加去实现取反过程,你想想时间复杂度是不是O(n),那有没有一种办法可以优化累加的时间复杂度呢?
  • 当然有。我们可以通过事先创建两个数组,分别去存储正负2的多少次方的值是多少。到时候,我们可以用循环的方式,去累加预定值,这样是不是就将时间复杂度O(n)缩短到O(logn)了呢?

OK,这道题讲到这里,大家应该心里很有谱了才对。做这道题,首先,我们要创建两个内置数组,去存储可能出现的2的次方值。然后先实现取反函数。再实现减法函数,再实现乘法函数,最后实现除法函数。

实现的过程中,需要大家注意溢出问题。因为虽然题目给的值的范围不会超过int的最大最小范围。但是两个数相减,相乘,相除的过程中,如果处理不好,是会发生溢出问题的。

具体的实现请看代码:

class Operations {
    int posN[31]; // 放正数2的n次方
    int negN[31]; // 放负数2的n次方
    //取相反数函数
    int oppN(int num){
        if(!num) return 0;
        int res = 0;
        if(num > 0){ // 从2^30次方开始检查
            for(int i = 30; i >= 0; i += (-1)){
                if(num + negN[i] < 0) continue;
                num += negN[i];
                res += negN[i];
            }
        }else{ // 从 - 2^30次方开始检查
            for(int i = 30; i >= 0; i += (-1)){
                if(num + posN[i] > 0) continue;
                num += posN[i];
                res += posN[i];
            }
        }
        return res;
    }
public:
    Operations() {
        int p = 1;
        int n = -1;
        posN[0] = p;
        negN[0] = n;
        // 初始化次方数组
        for(int i = 1; i < 31; ++i){
            p += p;
            posN[i] = p;
            n += n;
            negN[i] = n;
        }
    }

    
    int minus(int a, int b) {
        return a + oppN(b);
    }
    
    int multiply(int a, int b) {
        if(!a || !b) return 0;
        if(a == 1) return b;
        if(b == 1) return a;
        if(b < 0) return oppN(multiply(a,oppN(b))); // 统一b的正负
        int res = a;
        int count = 1;
        while(count < posN[30] && count + count <= b ){
            res += res;
            count += count;
        }
        res += multiply(a,minus(b,count));
        return res;
    }


    
    int divide(int a, int b) {
        if(!a) return 0;
        int res = 1;
        if(a > 0){
            if(b == INT_MIN) return 0;
            if(b < 0) return oppN(divide(a,oppN(b))); // 统一a,b的正负
            if(a < b) return 0;
            int count = b;
            while(count < posN[30] && a >= count + count){
                res += res;
                count += count;
            }
            res += divide(minus(a,count),b);
        }else{
            if(b == 1) return a;
            if(b > 0) return oppN(divide(a,oppN(b)));
            if(a > b) return 0;
            int count = b;
            while(count >= negN[30] && a <= count + count){
                res += res;
                count += count;
            }
            res += divide(minus(a,count),b);
        }
        return res;
    }    
};

在这里插入图片描述

复杂度分析

下面是这个代码中各个函数的时间复杂度和空间复杂度分析:

  • oppN(int num):时间复杂度为 O(log(num)),因为它在最坏情况下需要遍历数组 posN 或 negN 中的所有元素(共 31 个),这与输入数字的二进制表示长度成正比。空间复杂度为 O(1),因为它使用了固定数量的额外存储空间。

  • Operations() 构造函数:时间复杂度为 O(1),因为它只需要遍历 31 个元素并执行一定数量的操作。空间复杂度为 O(1),因为它只使用了固定大小的 posN 和 negN 数组。

  • minus(int a, int b):时间复杂度为 O(log(b)),因为它调用了 oppN 函数。空间复杂度为 O(1),因为它没有使用额外的存储空间。

  • multiply(int a, int b):时间复杂度为 O(log(a) * log(b)),因为它使用递归实现,每次递归调用都会减小 b 的值,递归深度为 O(log(b)),而每次递归调用都会调用 minus 函数,时间复杂度为 O(log(a))。空间复杂度为 O(log(b)),因为递归深度与空间复杂度成正比。

  • divide(int a, int b):时间复杂度为 O(log(a) * log(b)),因为它也是使用递归实现,每次递归调用都会减小 a 的值,递归深度为 O(log(a)),而每次递归调用都会调用 minus 函数,时间复杂度为 O(log(b))。空间复杂度为 O(log(a)),因为递归深度与空间复杂度成正比。

总的来说,这个实现的时间复杂度主要取决于输入数字的二进制表示长度,而空间复杂度主要取决于递归深度。

总结

  • 这道题的意义在于考察编程能力、逻辑思维和对基本运算的理解。

  • 它要求我们在限制条件下(仅使用加法运算符和逻辑运算符)实现整数数字的减法、乘法和除法运算。这种问题有助于锻炼思考能力,强化对计算机基本原理的理解,以及提高解决问题的灵活性。

  • 同时,这种问题也有助于理解计算机是如何处理基本的算术运算的,以及为什么某些优化方法(例如位运算)是有效的。通过解决这种问题,你可以加深对计算机科学和编程原理的理解。

  • 最后的最后,如果你觉得我的这篇文章写的不错的话,请给我一个赞与收藏,关注我,我会继续给大家带来更多更优质的干货内容

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/482793.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux【模拟实现C语言文件流】

✨个人主页&#xff1a; 北 海 &#x1f389;所属专栏&#xff1a; Linux学习之旅 &#x1f383;操作环境&#xff1a; CentOS 7.6 阿里云远程服务器 文章目录 &#x1f307;前言&#x1f3d9;️正文1、FILE 结构设计2、函数使用及分析3、文件打开 fopen4、文件关闭 fclose5、缓…

4.3 实施部署Nginx 高可用负载均衡集群

部署大致可分为&#xff1a;准备工作、配置、验证与交付几个步骤&#xff0c;接下来按顺序逐一介绍。 4.3.1 准备工作 Nginx高可以负载均衡集群准备工作分两个层面&#xff1a;前端负载均衡器的准备工作与后端真实服务器的准备工作。根据长期实践出来的经验&#xff0c;先准备后…

更轻更好用的蓝牙耳机,日常佩戴更舒适,QCY Crossky Link体验

平时为了方便接打电话&#xff0c;我经常会戴上一副蓝牙耳机&#xff0c;不过戴久了入耳式的耳机&#xff0c;总感觉不舒服&#xff0c;上个月我看到一款设计很新颖的开放式耳机&#xff0c;来自我之前用过的一个国产品牌&#xff0c;最近到手后试了试&#xff0c;感觉质量不错…

Pandoc 从入门到精通,你也可以学会这一个文本转换利器

Pandoc 简介 如果你需要在不同的文件格式之间相互转换&#xff0c;多半听说或使用过文档转换的瑞士军刀——Pandoc。事实上&#xff0c;不仅人类知道 Pandoc&#xff0c;最近很火的人工智能 ChatGPT 也知道「将 Markdown 转换为 docx」&#xff0c;首选方案是使用 Pandoc。 ​…

Codeforces Round 868 (Div. 2)

Problem - D - Codeforces 思路&#xff1a; 首先&#xff0c;一个位置至多贡献1&#xff0c;不然就是0.如[l1,r]与[l2,r]都是回文串&#xff08;l1<l2) 若(l1r)/2<l2,即[l2,r]本身就是[l1,r]回文串右边的一部分&#xff0c;那么他的贡献在[l1,r]左边已经计算过。如果(…

Python程序的执行过程

哈喽&#xff0c;大家好&#xff0c;五一快乐呀&#xff0c;都去哪里旅游了呢&#xff1f;再游玩之余也花点时间来学习学习&#xff0c;让自己更强哟。这期就给大家分享的是Python程序执行的过程学习。 之前已经给大家介绍了Python语言的简介、Python环境的安装、IDE的选择与安…

4 斐波那契数列

4 斐波那契数列 作者: Turbo时间限制: 1S章节: 递归 问题描述 : 斐波那契数列的排列是&#xff1a;0&#xff0c;1&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;5&#xff0c;8&#xff0c;13&#xff0c;21&#xff0c;34&#xff0c;55&#xff0c;89&#xff0c;…

CTF-PHP反序列化漏洞2-利用魔法函数

作者&#xff1a;Eason_LYC 悲观者预言失败&#xff0c;十言九中。 乐观者创造奇迹&#xff0c;一次即可。 一个人的价值&#xff0c;在于他所拥有的。可以不学无术&#xff0c;但不能一无所有&#xff01; 技术领域&#xff1a;WEB安全、网络攻防 关注WEB安全、网络攻防。我的…

.net 智慧手术麻醉管理系统 WCF框架

实用性&#xff1a; 充分考虑科室业务场景实用性&#xff0c;把满足临床需要为第一要素进行考虑。具有操作简单、提示清晰、逻辑性强&#xff0c;直观简洁等特点。 灵活可自定义&#xff1a; 软件设计采用模块式、组件式开发&#xff0c;根据临床需要可根据实际业务进行组合…

【MATLAB第26期】区间预测 | 基于MATLAB的LASSO分位数回归预测模型 负荷预测数据

【MATLAB第26期】区间预测 | 基于MATLAB的LASSO分位数回归预测模型 负荷预测数据 一、效果预览 MSE: 22.9684327801807 %15分钟 21.6725387054707%30分钟 24.0995456594418%45分钟 21.3992361173462%60分钟 二、数据选择 案例数据&#xff1a;两个月负荷数据3599*30&#x…

网络编程 总结三

一、并发服务器模型 【1】 循环服务器 1>一次只能处理一个客户端的请求&#xff0c;等待这个客户端退出后&#xff0c;才能处理下一个客户端 2>缺点&#xff1a;循环服务器所处理的客户端不能有耗时操作 //*****模型****** sfd socket(); bind(); listen(); while(1)…

springboot websocket通信

目录 一、websocket是什么 二、实现websocket 2.1参考学习b站资料&#xff08;一定要看&#xff0c;前后端详细&#xff09; 2.2学习配套代码 一、websocket是什么 WebSocket_ohana&#xff01;的博客-CSDN博客 二、实现websocket 2.1参考学习b站资料&#xff08;一定要看…

4 异常机制--数组、切片、算法【Go语言教程】

4 异常机制–数组、切片、算法【Go语言教程】 1 异常机制 1.1 处理错误 Go 语言追求简洁优雅&#xff0c;所以&#xff0c;Go 语言不支持传统的 try…catch…finally 这种处理。Go 中引入的处理方式为&#xff1a;defer, panic, recover这几个异常的使用场景可以这么简单描述…

【小沐学Python】Python实现Web服务器(Flask框架扩展:Flask-Admin)

文章目录 1、简介1.1 flask1.2 flask-admin 2、安装2.1 安装库2.2 打印库版本 3、初始化4、添加独立视图&#xff08;BaseView&#xff09;4.1 管理接口索引页4.2 自定义视图 5、添加模型视图&#xff08;ModelView&#xff09;6、添加特殊视图6.1 Managing Files & Folder…

VS2019配置redis客户端的c++开发环境

目录 需要的开源库&#xff1a; 具体步骤&#xff1a; 遇到的问题&#xff1a; 1. 确保每个项目使用的配置解决方案管理器一样 2.CMAKE 的安装 3. 使用 CMAKE 的路径配置 4. redis 编译报错&#xff1a;jemalloc/jemalloc.h没有这个文件&#xff0c;或者找不到.dll 5. linux …

【Linux】初识Linux --指令Ⅰ

Halo&#xff0c;这里是Ppeua。平时主要更新C语言&#xff0c;C&#xff0c;数据结构算法&#xff0c;Linux…感兴趣就关注我吧&#xff01;你定不会失望。 目录 1.ls 显示当前目录下的文件内内容2.pwd-显示用户当前所在的目录3.cd-改变工作目录。将当前工作目录改变到指定的目…

C++ STL-deque

deque&#xff1a;双端队列 目录 deque&#xff1a;双端队列 1、 基本介绍 2、使用方法 2.1、 头文件 2.2、 定义 2.3、 方法函数 3、排序 1、 基本介绍 首尾都可插入和删除的队列为双端队列。 deque容器是连续的空间&#xff0c;其他连续的行空间还有 array 和 vect…

E. Multihedgehog(多叉树找root节点)

Problem - E - Codeforces 有人给Ivan一个奇怪的生日礼物&#xff0c;这是一只刺猬 - 一个连通的无向图&#xff0c;其中一个顶点的度至少为3&#xff08;我们称其为中心&#xff09;&#xff0c;而所有其他顶点的度数均为1。Ivan认为刺猬太无聊了&#xff0c;决定自己制造k-多…

总结838

四月结束&#xff0c;五月来临。又到了月度总结与规划的时候了。 四月总结&#xff1a;高等数学原计划复习完18讲内容&#xff0c;刷完对应的习题。如今还剩三讲&#xff0c;本可以看完&#xff0c;但因为后面分专题了&#xff0c;还没确定是数1还是数2.所以耽搁了一下。英语原…

SG函数(博弈论)

一&#xff0c;定义 对于满足以下条件的公平二人游戏&#xff0c;均可以用sg函数&#xff08;暴搜&#xff09;获得答案 人数2人 两人交替进行合法操作&#xff0c;无法进行者LOSE对 于游戏的任意一种可能的局面&#xff0c;合法的操作集合只取决于这个局面的本身&#xff0c;…