面试 | 递归乘法【细节决定成败】

news/2024/4/19 14:11:06/文章来源:https://blog.csdn.net/Fire_Cloud_1/article/details/128758602

在这里插入图片描述

不用[ * ]如何使两数相乘❓

  • 一、题目明细
  • 二、思路罗列 & 代码解析
    • 1、野蛮A * B【不符合题意】
    • 2、sizeof【可借鉴】
      • 解析
    • 3、简易递归【推荐】
      • ① 解析(递归展开图)
      • ② 时间复杂度分析
    • 4、移位<<运算【有挑战性💪】
      • ① 思路顺理
      • ② 算法图解
      • ③ 代码分析
      • ④ 调试分析
    • 📺视频解说
  • 三、总结与提炼

一、题目明细

原题传送门

在这里插入图片描述

  • 可能有读者会说为什么那么简单的题目也要写个题解?
  • 答:细节决定成败,不可忽视细枝末节,对算法题的思考尽量要做到多维度考虑、多思考,继而找出最优解👑

二、思路罗列 & 代码解析

下面会列出我所AC的所有解,有些可能不符合题意

1、野蛮A * B【不符合题意】

本以为不让使用【*】运算符,但是试了一下,竟然也可以过😮

int multiply(int A, int B){return A * B;
}

在这里插入图片描述

2、sizeof【可借鉴】

这个方法我觉得还是比较巧妙,如果题目没有指定说要使用递归来进行求解,可以考虑

int multiply(int A, int B){char a[A][B];return sizeof(a);
}

在这里插入图片描述

解析

  • 有很多学习完C语言的同学在使用sizeof()的时候都会觉得它是一个函数,但真的是吗?其实可以去cpluplus中看看。就可以观测到无论是搜索多久都不会有结果

在这里插入图片描述

  • 其实对于sizeof()来说是一个操作符,而且是一个单目操作符,如果不清楚的可以看看我的操作符汇总大全。用来计算某一个数据类型的变量所占的字节大小。不要和Pascal中的sizeof()混淆了,在这门语言中是作为【函数】来看待的

Pascal 语言中,sizeof() 是一种内存容量度量函数,功能是返回一个变量或者类型的大小(以字节为单位);在 C语言中,sizeof() 是一个判断数据类型或者表达式长度的运算符《来源于百度百科》


  • 所以在这道题中,其实我们利用两数相乘的这个逻辑,去定义一个字符型的二维数组,然后将这个数组当做是长方体,那对于长方体的面积来说就是长 * 宽,那对于二维数组这个矩阵来说其实就是去计算它在内存中所占地字节数是多少,这样就可以很轻易地想到使用sizeof()去进行求解
  • 这里要注意的是需定义为【字符数组】,因为char类型的变量在内存中只占一个字节,若是定义为整型数组,算出来就是结果的4倍了!

在这里插入图片描述

3、简易递归【推荐】

这才是最符合题意的做法,使用递归去进行求解

class Solution {
public:int Mul(int big, int small){if(small == 0)  return 0;         //与0相乘一定为0if(small == 1)  return big;       //与1相乘一定为自身return big + Mul(big, small - 1);   //small个big相加,small递减}int multiply(int A, int B) {//首先区分两者中的大的那个和小的那个int big = A > B ? A : B;int small = A < B ? A : B;return Mul(big, small);}
};

在这里插入图片描述

① 解析(递归展开图)

递归对有些同学来说可能不好理解,因此讲说一下代码逻辑

  • 首先题目说到,两个数相乘不可以使用【*】号,那其实我们其看一下两个数相乘的原理也就是从加法转化过来的,例1:3 * 4 == 4 + 4 + 4 | 例2:2 * 5 == 5 + 5
  • 选取到小的那个数作为相加的次数
  • 选取大的那个数作为相加的数字

  • 在递归的函数中,若是发现small == 0,那直接return 0即可,因为任何数和0相乘都是0
  • 若是发现small == 1,那就直接返回big,因为任何数和1相乘都是1
  • 若是都不满足,则进行递归调用,注意要保留当前层的big,然后再产生递归让small - 1即可

若是感觉有点抽象的话,就通过递归展开图来看看吧
在这里插入图片描述

② 时间复杂度分析

  • 对于上面这种方法的时间复杂度为O(N)。准确点来说是O(small),相当于一个线性阶。如果对时间复杂度如何计算不是很懂,可以看看我的这篇文章——> 时间与空间复杂度就看这篇了
  • 那有没有更优的方法呢?就来看看下面这种吧

4、移位<<运算【有挑战性💪】

若是你搞懂了上面这种方法,那便来看看这种移位<<这种方法吧,会让你更上一层楼

int Mul(int big, int small)
{if(small == 0)  return 0;if(small == 1)  return big;int half_small = small >> 1;    //右移运算符,每次使small缩小一半//递归算出每一半的乘积int half_Sum = Mul(big, half_small);    //判断每一层的递归中的small为偶数还是奇数if(small % 2 == 0){return half_Sum + half_Sum;     //若为偶数直接是double倍}else{return half_Sum + half_Sum + big;   //若为奇数则还需加上一个big}
}int multiply(int A, int B){//1.划分二者的大小int big = A > B ? A : B;int small = A < B ? A :B;int ret = Mul(big, small);return ret;
}

在这里插入图片描述

① 思路顺理

  • 首先对于主接口函数还是一样,区分两者中谁大谁小,然后传入递归函数中
  • 在递归函数中,我的思路是这样的,既然在上一题中想到了线性阶,那便想要优化为对数阶,那对于对数阶而言一定存在一个二分的关系,然后就可以想到一半的关系
  • 所以对于small个big相乘,其实并不需要加small次,加small/2次即可,对于small/2次,其实也只需要加small/2次即可,那么这就相当于是一个递归的问题,要求出8个10的和,先求出4个10的和;要求出4个10的和,先求出2个10的和,要求出2个10的和,就先求出1个10,最后再进行层层回调,便可以算出small个big的和为多少了
  • 不过这个small的情况还是判断其为奇数还是偶数:对于偶数来说就是一个二分,但是对于奇数来说就不一样了,因为÷2之后相当于是一个整除,所以会漏掉一次的big相加,要在求当前和的最后加上一个big
  • 对于上述这种算法的时间复杂度很明显可以看出来是O(log2small)

② 算法图解

经过思路的讲解与分析,可能你还有些云里雾里😵那就通过算法分解图来看看吧

  • small为偶数的情况

在这里插入图片描述

  • small为奇数的情况

在这里插入图片描述

③ 代码分析

通过算法图的展示之后,相信你一定很清楚该如何去解决这个问题了,我们再来回顾一下代码

  • 若是small进来直接为0,那么直接return 0便可
if(small == 0)  return 0;
  • 这句便是算出当前层small的一半为多少,使用的便是移位运算符,右移是缩小1/2
int half_small = small >> 1;    //右移运算符,每次使small缩小一半
  • 求出当前层small的一半之后,就继续进行递归,
//递归算出每一半的乘积
int half_Sum = Mul(big, half_small); 
  • 若是当递归调用的时候small == 1了,便return big进行回调
if(small == 1)  return big;
  • 在回调之后,便会进行当前层一半总数的计算,这里就是我说的要对small进行奇偶数分类的情况
//判断每一层的递归中的small为偶数还是奇数
if(small % 2 == 0){return half_Sum + half_Sum;     //若为偶数直接是double倍
}else{return half_Sum + half_Sum + big;   //若为奇数则还需加上一个big
}

④ 调试分析

通过调试再来看看程序到底是如何运行的

  • big = 6, small = 4为例,进到递归函数中

在这里插入图片描述

  • 通过右移运算符>>便算出small的一半

在这里插入图片描述

  • 继续递归,直到small == 1为止

在这里插入图片描述

  • 此时small便为1,执行return big

在这里插入图片描述

  • 递归回来之后便计算当前层的总和,因为small == 2为偶数所以无需再加上big

在这里插入图片描述

  • 此时继续回调,算出small == 4这一层的总和

在这里插入图片描述

  • 最后便通过递归计算出了【4 * 6】的和为24

在这里插入图片描述


为了更好地对照算法图,也来测试一下奇数的情况

  • 这次的对比是运算是big = 8, small = 6

在这里插入图片描述

  • 可以看到,出现了small为奇数的情况

在这里插入图片描述

  • 继续递归,直到small == 1为止

在这里插入图片描述

  • 然后开始计算每一层的总和,注意:回到small == 3的递归层时,要进入第二个if分支

在这里插入图片描述

  • 此时就需要加上整除之后遗漏的那个big了

在这里插入图片描述

  • 回到small == 6的递归层时继续计算当前层的总和

在这里插入图片描述

  • 最后就算出了6 * 8 = 48的结果

在这里插入图片描述

📺视频解说

本文的题解都是通过看下面这位UP主写出来的,可以看看他的讲解——> 主页

leetcode 面试题 08.05. 递归乘法

三、总结与提炼

最后来总结一下本文所学习的内容📖

  • 【递归乘法】这道题是LeetCode上的一道面试题,虽然题目看起来比较简单,但是递归对很多同学来说还是比较困难,所以我在这里做一个细致的讲解
  • 主要是详细解说了有关递归的两种解法,对于简易递归来说就是本题的答案,但是我们要像在面试中胜出,就必须要想到更好、更优的解法;对于第二种sizeof的解法,可供读者参考,也是比较巧妙的方法,不过要清楚sizeof是一个操作符,而不是一个函数

学会不断思考,不断突破自己,才是最大的进步

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

啥是原神?女友说想要全角色语音+表情包,顺手用python把高清图也整下来了

原神全角色中日语音表情包高清图人生苦短 我用python表情包部分&#xff1a;1. 素材来自&#xff1a;2. 准备模块3. 调用浏览器驱动4. 页面滚动5. 保存数据5. 效果全角色语音高清彩图部分1.准备工具2. 准备模块3. 请求链接4. 本次目标5. 分析数据来源6. 开始代码7. 执行结果8. …

Revit操作 | 门和窗的载入与放置。

想要系统性掌握BIM技能&#xff0c;不能只停留在理论知识上&#xff0c;实操也是关键一步。 拒绝纸上谈兵&#xff0c;提升操作技巧&#xff0c;从点滴开始积累。今天我们来学习Revit实操小技巧之门和窗的载入与放置。 门和窗的载入与放置 门和窗是建筑中最常用的构件。在 Re…

单通道说话人语音分离——Conv-TasNet(Convolutional Time-domain audio separation Network)

单通道说话人语音分离——Conv-TasNet模型(Convolutional Time-domain audio separation Network) 参考文献&#xff1a;《Conv-TasNet: Surpassing Ideal Time-FrequencyMagnitude Masking for Speech Separation》 1.背景 在真实的声学环境中&#xff0c;鲁棒的语音处理通常…

Unity(二)--通过简单例子了解UGUI几个常用对象操作(Text,Image,Button)

目录 文本框等UI对象的添加Canvas 画布给Canvas添加脚本,绑定要操作的对象文本框Text的使用图像Image的使用更换图片Type:显示图片相关按钮Button的使用过渡导航事件绑定文本框等UI对象的添加 Canvas 画布 当创建一个UI元素的时候,如果没有Canvas 画布,就会自动创建一个画布…

PDMS二次开发(一)——PML类型程序类型与概念

目录前言一、PML类型与概念基础知识变量函数小例子注释PML表达式条件判断语句循环skip和break窗口程序在PDMS菜单栏中添加程序窗口自动定位PML常见控件前言 PDMS二次开发需要.net 有自带的PML语言和C# .net一般通常泛指的是C#语言 模型数据借助.NET的接口可以转换成数据库中的…

MSP430F2132IRHBR功能框图TPS259824LNRGER电路保护和电源管理解决方案芯片

概述&#xff1a;MSP430F21x2 16位超低功耗微控制器 (MCU) 是MSP430系列微控制器的一部分。这些MCU采用一种架构&#xff0c;加上5种低功耗模式&#xff0c;能在便携式测量应用中延长电池的使用寿命。这些器件具有一个强大的16位 RISC CPU、16位寄存器和用于获得最大编码效率的…

OpenStack手动分布式部署Glance【Queens版】

目录 Glance简介 1、登录数据库配置&#xff08;在controller执行&#xff09; 1.1登录数据库 1.2数据库里创建glance 1.3授权对glance数据库的正确访问 1.4退出数据库 1.5创建glance用户密码为000000 1.6增加admin角色 1.7创建glance服务 1.8创建镜像服务API端点 2、安装gla…

FinClip 的 2022 与 2023

相比往年&#xff0c;今年复盘去年与展望新年的文章来的稍慢一点。不过也希望能够借这篇文章&#xff0c;和关注 FinClip 的用户朋友们一起聊聊&#xff0c;我们在去年和今年的想法与计划。 2022 在过去的一年中&#xff0c;我们的身边发生了很多事情&#xff0c;这些事情在不…

CANoe-TestModule-vTESTstudio-Python -- 爱恨情仇

前面有聊过什么才是真正的自动化平台&#xff1b;其实说起来也是每个测试人的工作之路&#xff0c;从入门的测试执行、测试用例设计、自动化脚本开发、自动化架构开发、自动化平台开发&#xff0c;实际上我们大多数测试人都在纠结第一步的测试执行和第三步的自动化脚本开发&…

数据结构—堆(完全解析)

数据结构—堆&#xff08;完全解析&#xff09; 数据结构——堆&#xff08;Heap&#xff09;大根堆、小根堆 详解数据结构——堆 堆的基本存储 【从堆的定义到优先队列、堆排序】 10分钟看懂必考的数据结构——堆 【堆/排序】堆排序的两种建堆方法 【算法】排序算法之堆排序 C…

Mybatis学习记录

Mybatis学习记录一、MyBatis简介1.1、MyBatis历史1.2、MyBatis特性1.3、MyBatis下载1.4、和其他持久化层技术对比二、MyBatis框架搭建2.1、加入依赖2.2、创建MyBatis的核心配置文件2.3、创建Mapper接口2.4、 创建MyBatis的映射文件2.5、 测试环境2.6、 加入Log4j日志功能三、核…

Array.apply(null,{length: 99}) 逻辑解析

一、基础概述 vue 教程中有一段 demo code&#xff0c;如下&#xff1a; render: function (createElement) {return createElement(div,Array.apply(null, { length: 20 }).map(function () {return createElement(p, hi)})) }这个表达式Array.apply(null, { length: 20 })有…

Leetcode第450题删除二叉搜索树中的结点|C语言

题目&#xff1a; 给定一个二叉搜索树的根节点 root 和一个值 key&#xff0c;删除二叉搜索树中的 key 对应的节点&#xff0c;并保证二叉搜索树的性质不变。返回二叉搜索树&#xff08;有可能被更新&#xff09;的根节点的引用。 一般来说&#xff0c;删除节点可分为两个步骤…

【python】用plotly绘制正二十面体

文章目录顶点棱实现正二十面体plotly 的 Python 软件包是一个开源的代码库&#xff0c;它基于 plot.js&#xff0c;而后者基于 d3.js。我们实际使用的则是一个对 plotly 进行封装的库&#xff0c;名叫 cufflinks&#xff0c;能让你更方便地使用 plotly 和 Pandas 数据表协同工作…

最新文件快递柜系统网站源码-Fastapi+Sqlite3+Vue2+ElementUI-简洁好用

## 主要特色 - [x] 轻量简洁:Fastapi+Sqlite3+Vue2+ElementUI - [x] 轻松上传:复制粘贴,拖拽选择 - [x] 多种类型:文本,文件 - [x] 防止爆破:错误次数限制 - [x] 防止滥用:IP限制上传次数 - [x] 口令分享:随机口令,存取文件,自定义次数以及有效期 - [x] 匿名分享:无…

BurpSuite实战教程02-BurpSuite+夜神模拟器抓包教程

工具介绍 BurpSuite BurpSuite是用于“攻击”web 应用程序的集成平台&#xff08;java编写&#xff09;&#xff0c;包含了许多工具。Burp Suite为这些工具设计了许多接口&#xff0c;以加快攻击应用程序的过程。所有工具都共享一个请求&#xff0c;并能处理对应的HTTP 消息、…

使用Autoware标定工具包联合标定相机和激光雷达

前面文章介绍了&#xff0c;安装autoware标定工具包、ros驱动usb相机、robosense-16线激光雷达的使用&#xff0c;本文记录使用Autoware标定工具包联合标定相机和激光雷达的过程。1.ros驱动相机&#xff0c;启动相机&#xff1b;启动激光雷达2.联合录制bag包rosbag record -a 参…

k8s1.23.0+ubuntu20.04+docker23+hyperv

问题 k8s node节点加入到集群时卡住 “[preflight] Running pre-flight checks” # master节点重新生成加入命令 kubeadm token create --ttl 0 --print-join-command参考 注意 k8s1.24使用containerd而不再使用docker&#xff0c;因此使用k8s1.23版本 环境 k8s: 1.23.0 u…

TestNG和Junit的区别,测试框架该如何选择?

要想知道两个框架的区别&#xff0c;首先分别介绍一下两个框架。 TestNG是一个java中的开源自动化测试框架&#xff0c;其灵感来自JUnit和NUnit&#xff0c;TestNG还涵盖了JUnit4整个核心的功能&#xff0c;但引入了一些新的功能&#xff0c;使其功能更强大&#xff0c;使用更…

记一次docker虚拟机横向移动渗透测试

本次渗透在几个docker虚拟机间多次横向移动&#xff0c;最终找到了一个可以进行docker逃逸的出口&#xff0c;拿下服务器。渗透过程曲折但充满了乐趣&#xff0c;入口是172.17.0.6的docker虚拟机&#xff0c;然后一路横向移动&#xff0c;最终在172.17.0.2出实现了docker逃逸&a…