面试题08.05.递归算法

递归乘法。 写一个递归函数,不使用 * 运算符, 实现两个正整数的相乘。可以使用加号、减号、位移,但要吝啬一些。

示例1:

复制代码
 输入:A = 1, B = 10
 输出:10

示例2:

复制代码
 输入:A = 3, B = 4
 输出:12

提示:

  1. 保证乘法范围不会溢出

我的答案:

一、信息

**- 需要实现一个递归函数来完成两个正整数的乘法。

  • 不可以使用`*`运算符。
  • 可以使用加号、减号、位移。
  • 需要尽可能地减少操作的使用,即要吝啬一些。**

二、分析

**#### 思考过程中问题的出现:

  1. **如何不使用`*`运算符来实现乘法?**
  • 乘法可以看作是多次加法。例如,`3 * 4`可以看作是`4 + 4 + 4`。
  1. **如何使用递归来实现乘法?**
  • 可以将一个数分解为多个较小的数的和,然后递归地计算这些较小的数的乘积。**

**3. **如何减少操作的使用?**

  • 可以使用位移操作来实现快速加法和减法。
  • 可以通过减少递归的深度来减少操作的使用。**

**#### 问题的答案:

  1. **乘法的实现**:
  • 通过递归和加法来实现乘法。
  1. **递归的使用**:
  • 将一个数分解为多个较小的数的和,然后递归地计算这些较小的数的乘积。**

**3. **减少操作的使用**:

  • 使用位移来实现快速加法和减法。
  • 通过优化递归的实现来减少递归的深度。**

**#### 思路:

  1. **基础思路**:
  • 将乘法`A * B`看作是`A`加自己`B`次,或者`B`加自己`A`次。
  • 使用递归来实现多次加法。**

**2. **优化思路**:

  • 使用位移操作来实现快速加法和减法。
  • 优化递归的实现,减少递归的深度。**

三、步骤(算法流程图)

**1. **基准情况**:

  • 如果`A`或`B`中的任何一个为`1`,返回另一个数。
  • 如果`A`或`B`中的任何一个为`0`,返回`0`。**

**2. **递归步骤**:

  • 将`A`或`B`分解为两个较小的数的和,例如`A = A1 + A2`,`B = B1 + B2`。
  • 递归地计算这些较小的数的乘积,例如`A1 * B1`,`A1 * B2`,`A2 * B1`,`A2 * B2`。
  • 将这些乘积的结果相加,得到最终的乘积。**

**3. **优化**:

  • 使用位移操作来实现快速加法和减法。
  • 优化递归的实现,例如通过记忆化来避免重复计算。**

这个流程图可以用伪代码来表示,如下:

function multiply(A, B):
    if A == 1:
        return B
    if B == 1:
        return A
    if A == 0 or B == 0:
        return 0
    
    A1, A2 = decompose(A)
    B1, B2 = decompose(B)
    
    product1 = multiply(A1, B1)
    product2 = multiply(A1, B2)
    product3 = multiply(A2, B1)
    product4 = multiply(A2, B2)
    
    return product1 + product2 + product3 + product

在实际实现时,可以进一步优化这个算法,例如通过记忆化来避免重复计算,或者通过位移操作来实现快速加法和减法。

四、具体实现

#### C语言实现

cpp 复制代码
#include <stdio.h>

int multiply(int A, int B) {
    if(A == 1) return B;
    if(B == 1) return A;
    if(A == 0 || B == 0) return 0;
    
    return B + multiply(A - 1, B);
}

int main() {
    printf("%d\n", multiply(1, 10)); // 输出10
    printf("%d\n", multiply(3, 4)); // 输出12
    return 0;
}

#### C++语言实现

cpp 复制代码
#include <iostream>

class Solution {
public:
    int multiply(int A, int B) {
        if(A == 1) return B;
        if(B == 1) return A;
        if(A == 0 || B == 0) return 0;
        
        return B + multiply(A - 1, B);
    }
};

int main() {
    Solution solution;
    std::cout << solution.multiply(1, 10) << std::endl; // 输出10
    std::cout << solution.multiply(3, 4) << std::endl; // 输出12
    return 0;
}

#### Java语言实现

java 复制代码
public class Solution {

    public int multiply(int A, int B) {
        if(A == 1) return B;
        if(B == 1) return A;
        if(A == 0 || B == 0) return 0;
        
        return B + multiply(A - 1, B);
    }

    public static void main(String[] args) {
        Solution solution = new Solution();
        System.out.println(solution.multiply(1, 10)); // 输出10
        System.out.println(solution.multiply(3, 4)); // 输出12
    }
}

五、检查错误

**在实际编写代码时,需要注意以下几点:

  1. **递归终止条件**:确保所有的基准情况都被正确处理,例如`A`或`B`为`1`或`0`的情况。
  2. **递归调用**:确保递归调用的参数是正确的,避免无限递归。
  3. **返回值**:确保在所有路径上都有返回值。**

六、三种语言实现的异同

**#### 相同点:

  1. **逻辑结构**:三种语言的实现在逻辑结构上是相同的,都是基于递归的方法来实现乘法。
  2. **基准情况**:三种语言都需要处理基准情况,即`A`或`B`为`1`或`0`的情况。
  3. **递归调用**:三种语言都使用递归调用来实现乘法。**

**#### 不同点:

  1. **语法**:三种语言的语法有所不同,例如函数定义和调用的语法。
  2. **输出**:三种语言输出的方式不同,C语言使用`printf`,C++使用`cout`,Java使用`System.out.println`。
  3. **类的使用**:在C++和Java中,代码是以类的形式组织的,而在C语言中,代码是以函数的形式组织的。**

这些实现都是基于递归的简单实现,可以进一步优化,例如通过记忆化来避免重复计算,或者通过位移操作来实现快速加法和减法。

七、学习收获

**1. **递归的应用**:

  • 通过这道题目,我们学习了如何使用递归来解决问题,特别是如何将一个问题分解成更小的子问题,然后递归地解决这些子问题。**

**2. **基础算法概念**:

  • 我们学习了乘法可以被看作是重复的加法,这是一个基础但重要的概念,帮助我们理解了算法是如何工作的。**

**3. **编程实践与思维训练**:

  • 编写代码来实现算法使我们得以实际操作来理解递归的工作原理,这对于培养逻辑思维和编程能力都是非常有帮助的。**

**4. **多语言实现与比较**:

  • 通过在不同的编程语言中实现相同的算法,我们学习了这些语言之间的相似性和差异性,这有助于我们更好地理解和掌握这些语言。**

**5. **问题分析与解决策略**:

  • 我们学习了如何分析问题,如何在给定的约束条件下寻找解决方案,这对于培养我们的问题解决能力和创新思维都是非常重要的。**

**6. **优化思维**:

  • 虽然这道题目的基础实现相对简单,但它提供了优化的可能性,例如通过记忆化来避免重复计算,这有助于培养我们的优化思维。**

**7. **算法的通用性**:

  • 这道题目展示了算法的通用性,即同一算法可以在不同的语言中实现,并且可以应用于不同的问题中。**

**8. **递归的优化与限制**:

  • 通过实践,我们可以更加深入地理解递归的优势与局限,例如递归可能导致的栈溢出问题,以及如何通过各种策略来优化递归。**

### 总结:
这道题目不仅提供了对递归和基础算法概念的实践,还通过多语言实现展示了编程语言的异同,同时也提供了对问题分析、解决策略和优化思维的训练。这些都是计算机科学和编程领域中非常重要的知识和技能。

不熟悉递归的读者你们可以看看我的递归文章传送门7.6 函数的递归调用

相关推荐
哎呦没23 分钟前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
小飞猪Jay29 分钟前
C++面试速通宝典——13
jvm·c++·面试
Kalika0-040 分钟前
猴子吃桃-C语言
c语言·开发语言·数据结构·算法
编程、小哥哥1 小时前
netty之Netty与SpringBoot整合
java·spring boot·spring
sp_fyf_20241 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-02
人工智能·神经网络·算法·计算机视觉·语言模型·自然语言处理·数据挖掘
rjszcb1 小时前
一文说完c++全部基础知识,IO流(二)
c++
IT学长编程2 小时前
计算机毕业设计 玩具租赁系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·课程设计·毕业论文·计算机毕业设计选题·玩具租赁系统
莹雨潇潇2 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器
杨哥带你写代码2 小时前
足球青训俱乐部管理:Spring Boot技术驱动
java·spring boot·后端
小字节,大梦想2 小时前
【C++】二叉搜索树
数据结构·c++