8.5Recursive Multiply

2024-01-04 19:18
文章标签 8.5 recursive multiply

本文主要是介绍8.5Recursive Multiply,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Problem

Write a recursive function to multiply two positive integers without using the * operator (or / operator). You can use addition, subtraction, and bit shifting, but you should
minimize the number of those operations.

Solution

首先考虑一下做乘法意味着什么。思考一件事情到底意味着什么通常是很有用的,即使是在非常明显的情况下。

来看一下进行8 * 7,可以通过8个7相加或者7个8相加得到结果。我们也可以它认为是一个8 * 7的网格中方块的个数。

Solution1

  我们如何计算一个网格中方块的个数?最简单的方法就是一个个去数。但是,这真的很慢。
  我们还可以数一半的方块的个数,然后将它加倍(通过将它和自己相加)。为了计算一半方块的个数,我们重复同样的过程。
  当然,只有当方块的个数是偶数时,上述算法才能工作。当方块个数是奇数时,我们需要从头来做。

int minProductHelper(int smaller,int bigger)
{if(smaller == 0)//0*bigger = 0return 0;else if(smaller == 1)//1*bigger = biggerreturn bigger;int halfSmaller = smaller >> 1;int side1 = minProductHelper(halfSmaller,bigger);int side2 = side1;if(smaller %2 == 1)side2 = minProductHelper(smaller - halfSmaller,bigger);return side1 + side2;
}int minProduct(int a,int b)
{int bigger = a < b?b:a;int smaller = a < b?a:b;return minProductHelper(smaller,bigger);}

Solution2

  如果我们观察递归如何进行,就会发现我们做了很多重复工作。考虑下面的例子:
  这里写图片描述
对minProduct(4,23)的第二次调用不知道之前的调用,所以做了重复的工作做。我们可以缓存这些结果。

int minProductHelper(int smaller,int bigger,vector<int>& memo)
{if(smaller == 0)//0*bigger = 0return 0;else if(smaller == 1)//1*bigger = biggerreturn bigger;else if(memo[smaller] > 0)return memo[smaller];int halfSmaller = smaller >> 1;int side1 = minProductHelper(halfSmaller,bigger,memo);int side2 = side1;if(smaller %2 == 1)side2 = minProductHelper(smaller - halfSmaller,bigger,memo);memo[smaller] = side1 + side2;return memo[smaller];
}int minProduct(int a,int b)
{int bigger = a < b?b:a;int smaller = a < b?a:b;vector<int> memo(smaller+1,-1);return minProductHelper(smaller,bigger,memo);}

Solution3

  当我们看前面的代码时我们会发现使用偶数来调用minProduct的速度要比使用奇数来调用要快得多。例如,如果我们调用minProduct(30,35),那么我们只需要计算minProduct(15,35)然后将它翻倍就行了。但是,如果我们要计算minProduct(31,35),那么我们就需要调用minProduct(15,35)和minProduct(16,35)。
  这不是必须的。相反,我们可以这样做:
  minProduct(31,35) = 2*minProduct(15,35) + 35
因为31 = 2*15 + 1,所以31 *35 = 2 *15 *35 + 35。
  最后这个解法的逻辑就是:偶数时,我们将smaller除以2,将递归调用的结果翻倍;奇数时,我们与偶数时的操作相同,但是要加上bigger之后作为最后的结果。
  这样做,还带来了另一个好处。我们的minProduct一直向下递归,每次都是用更小的数调用。因为不会出现重复调用的情况,所以没有缓存信息的需要。
  

int minProductHelper(int smaller,int bigger)
{if(smaller == 0)//0*bigger = 0return 0;else if(smaller == 1)//1*bigger = biggerreturn bigger;int halfSmaller = smaller >> 1;int side1 = minProductHelper(halfSmaller,bigger);int side2 = side1;if(smaller %2 == 1)side2+=bigger;return side1 + side2;
}int minProduct(int a,int b)
{int bigger = a < b?b:a;int smaller = a < b?a:b;return minProductHelper(smaller,bigger);}

这个算法的时间复杂度时O(log s),其中s是两个数中比较小的那一个。

这篇关于8.5Recursive Multiply的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/570330

相关文章

【运维监控】influxdb 2.0+telegraf 监控tomcat 8.5运行情况(1)

关于java应用的监控本系列有文章如下: 【运维监控】influxdb 2.0+telegraf 监控tomcat 8.5运行情况 【运维监控】influxdb 2.0+grafana 监控java 虚拟机以及方法耗时情况 【运维监控】Prometheus+grafana监控tomcat运行情况 【运维监控】Prometheus+grafana监控spring boot 3运行情况 本示例是通过

美国原装二手KEITHLEY2002数字万用表8.5位

吉时利Keithley 2002数字万用表,8.5 位 Keithley 2002 的分辨率规格基于 28 位 A/D 转换器,可提供辨别较小变化所需的分辨率。这种更高的分辨率还提供了更大的动态范围,使其能够在单个范围内测量从 1μV 到 20V 的电压,从而避免范围偏移误差和延迟。 2002 提供许多此类仪器通常不具备的内置测量功能,包括电路内电流、热电偶或 RTD 的温度以及峰值尖峰。与限

【运维监控】influxdb 2.0+telegraf 监控tomcat 8.5运行情况(2)

关于java应用的监控本系列有文章如下: 【运维监控】influxdb 2.0+telegraf 监控tomcat 8.5运行情况 【运维监控】influxdb 2.0+grafana 监控java 虚拟机以及方法耗时情况 【运维监控】Prometheus+grafana监控tomcat运行情况 【运维监控】Prometheus+grafana监控spring boot 3运行情况 本示例是通过

vue3 el-menu 菜单Maximum recursive updates exceeded 报错

vue3 用el-menu实现管理后台左侧菜单,报Uncaught (in promise) Maximum recursive updates exceeded in component <ElMenu>. This means you have a reactive effect that is mutating its own dependencies and thus recursivel

【C++ Primer Plus习题】8.5

问题: 解答: #include <iostream>using namespace std;template <typename T>T max5(T arr[5]){T max = 0;for (int i = 0; i < 5; i++){if (arr[i] > max){max = arr[i];}}return max;}int main(){int max =

Plus and Multiply(1500)

Plus and Multiply 题面翻译 有一个无穷大的正整数集合 S S S,该集合按下面所述方法生成: 数字 1 1 1 在集合 S S S 中。 若数字 x x x 在该集合中,那么数 x × a x \times a x×a 和数 x + b x+b x+b 均在集合 S S S 中。(其中 a a a 与 b b b 为给定常数) 现在给出数 n ,

ABC 368 G - Add and Multiply Queries

原题链接:G - Add and Multiply Queries 题意:给出数组a和b,三种操作,第一种:以 1 i x 的形式给出。用x替换ai​。第二种:以 2 i x 的形式给出。用x代替 bi​ 。第三种:以3 l r的形式给出,初始值为0,从l到r每个位置上可以选择加上a[i],或者乘上b[i],输出最大值。 思路:链表+set+树状数组+二分。题目中给出了答案的范围不会超过1e1

Add and Multiply Queries

题目链接:G - Add and Multiply Queries 区间修改+区间查询可以用线段树来做,但是这边介绍树状数组的写法。首先将a数组和b数组分开考虑,对于a数组,因为是加法运算求区间和,因此我们可以采用树状数组+差分来写,对于数组b,我们已知如果b[i] =  1 ,那么不如就进行加法运算,所以我们把b数组中大于1的数加入到一个set集合中,记住set记录的是位置,不是数值,然后可以

[leetcode] 43. Multiply Strings(大数相乘)

Multiply Strings 描述 Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2. Note: 1. The length of both num1 and num2 is < 110. 2. Both num1 an

拼多多 8.5笔试

输入:s = “abcdefghijklmnop” 输出: abcdep fo gn hmlkji 思路:计算坐标即可。关键在于中间部分,观察知第一列和最后一列坐标相加为15 + 5 = 20 = 5*(n-1) import syss = "abcdefgh" #样例k = len(s) #总数n = (k+4)//4 #边长print(s[0:n])