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

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

在这里插入图片描述

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

  • 一、题目明细
  • 二、思路罗列 & 代码解析
    • 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是一个操作符,而不是一个函数

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

在这里插入图片描述

相关文章:

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

不用[ * ]如何使两数相乘❓一、题目明细二、思路罗列 & 代码解析1、野蛮A * B【不符合题意】2、sizeof【可借鉴】解析3、简易递归【推荐】① 解析&#xff08;递归展开图&#xff09;② 时间复杂度分析4、移位<<运算【有挑战性&#x1f4aa;】① 思路顺理② 算法图解…...

【Linux】环境变量与进程优先级

文章目录&#x1f3aa; 进程优先级&#x1f680;1.孤儿进程&#x1f680;2.优先级查看&#x1f680;3.优先级修改&#x1f3aa; 环境变量&#x1f680;1.常见环境变量&#x1f680;2.环境变量获取&#x1f680;3.main中的命令行参数&#x1f3aa; 进程优先级 每个进程都有相应…...

RocketMQ5.0.0的Broker主从同步机制

目录 一、主从同步工作原理 1. 主从配置 2. 启动HA 二、主从同步实现机制 1. 从Broker发送连接事件 2. 主Broker接收连接事件 3. 从Broker反馈复制进度 4. ReadSocketService线程读取从Broker复制进度 5. WriteSocketService传输同步消息 6. GroupTransferService线程…...

深度学习论文: EdgeYOLO: An Edge-Real-Time Object Detector及其PyTorch实现

深度学习论文: EdgeYOLO: An Edge-Real-Time Object Detector及其PyTorch实现 EdgeYOLO: An Edge-Real-Time Object Detector PDF: https://arxiv.org/pdf/2302.07483.pdf PyTorch代码: https://github.com/shanglianlm0525/CvPytorch PyTorch代码: https://github.com/shangli…...

如何做好APP性能测试?

随着智能化生活的推进&#xff0c;我们生活中不可避免的要用到很多程序app。有的APP性能使用感很好&#xff0c;用户都愿意下载使用&#xff0c;而有的APP总是出现卡顿或网络延迟的情况&#xff0c;那必然就降低了用户的好感。所以APP性能测试对于软件开发方来说至关重要&#…...

Hive窗口函数

概述 窗口函数&#xff08;window functions&#xff09;也叫开窗函数、OLAP函数。 如果函数具有over子句&#xff0c;则它是窗口函数 窗口函数可以简单地解释为类似于聚合函数的计算函数&#xff0c;但是通过group by 子句组合的 常规聚合会隐藏正在聚合的各个…...

C++学习笔记(1):在默认构造函数内部使用带参数的构造函数

题目以下代码的输出是不是0&#xff1a;#include <unordered_map> #include <iostream>using namespace std;struct CLS{int i;CLS(int i_) :i(i_){}CLS(){CLS(0);} };int main(){CLS obj;std::cout << obj.i << endl;return 0; }结果-858993460为什么…...

Android面试题_安卓面经(23/30)设计模式源码案例

系列专栏: 《150道安卓常见面试题全解析》 安卓专栏目录见帖子 : 安卓面经_anroid面经_150道安卓基础面试题全解析 安卓系统Framework面经专栏:《Android系统Framework面试题解析大全》 安卓系统Framework面经目录详情:Android系统面经_Framework开发面经_150道面试题答案解…...

Dubbo性能调优参数以及原理

Dubbo作为一个服务治理框架&#xff0c;功能相对来说比较完善&#xff0c;性能也挺不错。但很多同学在使用dubbo的时候&#xff0c;只是简单的参考官方说明进行配置和应用&#xff0c;并没有过多的去思考一些关键参数的意义&#xff0c;最终做出来的效果总是差强人意,接下来我们…...

vue3全家桶之vuex和pinia持久化存储基础(二)

一.vuex数据持久化存储 这里使用的是vuex4.1.0版本,和之前的vuex3一样,数据持久化存储方案也使用 vuex-persistedstate,版本是最新的安装版本,当前可下载依赖包版本4.1.0&#xff0c;接下来在vue3项中安装和使用&#xff1a; 安装vuex-persistedstate npm i vuex-persisteds…...

LAMP架构与搭建论坛

目录 1、LAMP架构简述 2、各组件作用 3、构建LAMP平台 1.编译安装Apache httpd服务 2.编译安装mysql 3.编译安装php 4.搭建一个论坛 1、LAMP架构简述 LAMP架构是目前成熟的企业网站应用模式之一&#xff0c;指的是协同工作的一整台系统和相关软件&#xff0c;能够提供动…...

代码随想录 || 回溯算法93 78 90

Day2493.复原IP地址力扣题目链接给定一个只包含数字的字符串&#xff0c;复原它并返回所有可能的 IP 地址格式。有效的 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 . 分隔。例如&#…...

界面组件Kendo UI for Angular——让网格数据信息显示更全面

Kendo UI致力于新的开发&#xff0c;来满足不断变化的需求&#xff0c;通过React框架的Kendo UI JavaScript封装来支持React Javascript框架。Kendo UI for Angular是专用于Angular开发的专业级Angular组件&#xff0c;telerik致力于提供纯粹的高性能Angular UI组件&#xff0c…...

【Linux】进程状态|优先级|进程切换|环境变量

文章目录1. 运行队列和运行状态2. 进程状态3. 两种特殊的进程僵尸进程孤儿进程4. 进程优先级5. 进程切换进程特性进程切换6. 环境变量的基本概念7. PATH环境变量8. 设置和获取环境变量9. 命令行参数1. 运行队列和运行状态 &#x1f495; 运行队列&#xff1a; 进程是如何在CP…...

合宙Air780E|FTP|内网穿透|命令测试|LuatOS-SOC接口|官方demo|学习(18):FTP命令及应用

1、FTP服务器准备 本机为win11系统&#xff0c;利用IIS搭建FTP服务器。 搭建方式可参考博文&#xff1a;windows系统搭建FTP服务器教程 windows系统搭建FTP服务器教程_程序员路遥的博客-CSDN博客_windows服务器安装ftp 设置完成后&#xff0c;测试FTP&#xff08;已正常访问…...

大规模 IoT 边缘容器集群管理的几种架构-4-Kubeedge

前文回顾 大规模 IoT 边缘容器集群管理的几种架构-0-边缘容器及架构简介大规模 IoT 边缘容器集群管理的几种架构-1-RancherK3s大规模 IoT 边缘容器集群管理的几种架构-2-HashiCorp 解决方案 Nomad大规模 IoT 边缘容器集群管理的几种架构-3-Portainer &#x1f4da;️Reference…...

Spring底层核心原理解析

Spring简介 ClassPathXmlApplicationContext context new classPathXmlApplicationContext("spring.xml"); UserService userService (UserService) context.getBean("userService"); userService.test();上面一段代码是我们开始学习spring时看到的&…...

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…...

谈一谈你对View的认识和View的工作流程

都2023年了&#xff0c;不会还有人不知道什么是View吧&#xff0c;不会吧&#xff0c;不会吧。按我以往的面试经验来看&#xff0c;View被问到的概率不比Activity低多少哦&#xff0c;个人感觉View在Android中的重要性也和Activity不相上下&#xff0c;所以这篇文章将介绍下Vie…...

Redis集群的脑裂问题

集群脑裂导致数据丢失怎么办&#xff1f; 什么是脑裂&#xff1f; 先来理解集群的脑裂现象&#xff0c;这就好比一个人有两个大脑&#xff0c;那么到底受谁控制呢&#xff1f; 那么在 Redis 中&#xff0c;集群脑裂产生数据丢失的现象是怎样的呢&#xff1f; 在 Redis 主从架…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述&#xff1a;海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而&#xff0c;目前该领域仍面临一个挑战&#xff0c;即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

C++ 设计模式 《小明的奶茶加料风波》

&#x1f468;‍&#x1f393; 模式名称&#xff1a;装饰器模式&#xff08;Decorator Pattern&#xff09; &#x1f466; 小明最近上线了校园奶茶配送功能&#xff0c;业务火爆&#xff0c;大家都在加料&#xff1a; 有的同学要加波霸 &#x1f7e4;&#xff0c;有的要加椰果…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

为什么要创建 Vue 实例

核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...