• nowcoder NC10 大数乘法


    题目链接: icon-default.png?t=N7T8https://www.nowcoder.com/practice/c4c488d4d40d4c4e9824c3650f7d5571?tpId=196&tqId=37177&rp=1&ru=/exam/company&qru=/exam/company&sourceUrl=%2Fexam%2Fcompany&difficulty=undefined&judgeStatus=undefined&tags=&title=

    目录

    题目描述:

    答案:

    详解: 


    题目描述:

    以字符串的形式读入两个数字,编写一个函数计算它们的乘积,以字符串形式返回。

    数据范围: 读入的数字大小满足 0 \leqslant n \leqslant {10}^{1000}

    要求:空间复杂度 O(m),时间复杂度 O(m^{2})(假设m是n的长度)

    示例1:

    输入:"11","99"

    返回值:"1089"

    说明:11*99=1089

    示例2:

    输入:"1","0"

    返回值:"0"

    答案:

    1. import java.util.*;
    2. public class Solution {
    3. public String solve (String s, String t) {
    4. // write code here
    5. if (s.charAt(0) == '0' || t.charAt(0) == '0'){
    6. return "0";
    7. }
    8. String ret = "0";
    9. String[] tmp = new String[t.length()];
    10. for (int i = t.length() - 1; i >= 0; i--){
    11. tmp[i] = "";
    12. int j = t.length() - 1;
    13. while(j - i > 0){
    14. tmp[i] += '0';
    15. j--;
    16. }
    17. tmp[i] += alongMultiply(s, t.charAt(i));
    18. }
    19. for (int i = t.length() - 1; i >= 0; i--){
    20. ret = Add(tmp[i], ret);
    21. }
    22. //将结果逆置
    23. StringBuffer stringBuffer = new StringBuffer();
    24. for (int i = ret.length() - 1; i >= 0; i--){
    25. stringBuffer.append(ret.charAt(i));
    26. }
    27. ret = stringBuffer.toString();
    28. //也可以写成这样
    29. //tmp[0] = ret;
    30. //ret = "";
    31. //for (int i = tmp[0].length() - 1; i >= 0; i--){
    32. // ret += tmp[0].charAt(i);
    33. //}
    34. return ret;
    35. }
    36. public String Add(String a, String b){
    37. String str = "";
    38. int aLen = a.length() - 1;
    39. int ai = 0;
    40. int bLen = b.length() - 1;
    41. int bi = 0;
    42. int ten = 0;
    43. while(aLen >= ai && bLen >= bi){
    44. int tmp = (a.charAt(ai++) - '0') + (b.charAt(bi++) - '0');
    45. tmp += ten;
    46. ten = tmp / 10;
    47. str += tmp % 10;
    48. }
    49. while(aLen >= ai){
    50. int tmp = a.charAt(ai++) - '0';
    51. tmp += ten;
    52. ten = tmp / 10;
    53. str += tmp % 10;
    54. }
    55. while(bLen >= bi){
    56. int tmp = b.charAt(bi++) - '0';
    57. tmp += ten;
    58. ten = tmp / 10;
    59. str += tmp % 10;
    60. }
    61. if (ten != 0){
    62. str += ten;
    63. }
    64. return str;
    65. }
    66. public String alongMultiply(String s, char t){
    67. String ret = "";
    68. if (s.charAt(0) == '0' || t == '0'){
    69. return "0";
    70. }
    71. int tt = t - '0';
    72. int ten = 0;
    73. for (int i = s.length() - 1; i >= 0; i--){
    74. int tmp = s.charAt(i) - '0';
    75. tmp *= tt;
    76. tmp += ten;
    77. ten = tmp / 10;
    78. ret += tmp % 10;
    79. }
    80. if (ten != 0){
    81. ret += ten;
    82. }
    83. return ret;
    84. }
    85. }

    详解: 

     从题目中我们可以得到以下几点信息:

    1. 输入值和返回值都是字符串类型;
    2. 输入值和返回值不可以直接转换成整数(因为数字过大);
    3. 对时间复杂度几乎没有要求;
    4. 不会出现负数乘法。

     当我们清楚了题目要求之后就该考虑该如何解题了。

     首先我们应该考虑的是乘法是如何进行计算的

    我们以 11 * 99 为例:

    我们可以分析得到无论是几位数的乘法都是按照以下步骤进行的:

    1. 将第一个数字分别乘以第二个数的每一位;
    2. 如果第一个数乘的是第二个数的个位就给结果乘一,十位就乘十 以此类推;
    3. 最后一步就是将各各结果相加。

    到这一步之后如果你想在题目给的那一个方法里面实现这些内容就会大大提高你写代码的难度,此时其实我推荐将其用三个方法来实现。

    • 第一个为主函数,主要用来实现代码的整体思路;
    • 第二个为相乘的方法,其主要功能是实现一个 n 位数与一位数相乘;
    • 第三个为相加的方法,其主要功能是实现两个 n 位数的相加。

    根据乘法的定义可以知道:0 与任何数相乘都是 0 所以我们的第一段代码就可以为:

    1. public String solve (String s, String t) {
    2. // write code here
    3. if (s.charAt(0) == '0' || t.charAt(0) == '0'){
    4. return "0";
    5. }
    6. }

    接下来就是对每一位进行相乘但是我们并不知道是 几位数与几位数进行相乘 所以我们此时应该根据 t 的长度来定义一个字符串数组 tmp 用来存储 t 中的每一位与 s 相乘的结果。

    再定义一个名为 alongMultiply() 的方法 此方法就用来实现n 位数与一位数相乘并将其值以字符串的形式进行返回。(此方法可以先不急着实现)。

    再定义一个名为 的字符串类型的变量,将其初始化为“0” 用来存储最终的返回值。

    因为会有进位而导致最后结果的位数充满不确定性所以我们可以采用倒序的存储方式 

    即:12345 存储为 54321

    因为加法也会有进位所以我们可以在主方法的最后统一进行反转。

    1. public String solve (String s, String t) {
    2. // write code here
    3. if (s.charAt(0) == '0' || t.charAt(0) == '0'){
    4. return "0";
    5. }
    6. String ret = "0";
    7. //新加的代码
    8. String[] tmp = new String[t.length()];
    9. for (int i = t.length() - 1; i >= 0; i--){
    10. tmp[i] = "";
    11. int j = t.length() - 1;
    12. while(j - i > 0){ //相当于十位乘十 , 百位乘一百……
    13. tmp[i] += '0';
    14. j--;
    15. }
    16. tmp[i] += alongMultiply(s, t.charAt(i));
    17. }
    18. }

    紧接着我们再将 tmp数组 中的所有值进行相加存储在 ret 中。

    1. for (int i = t.length() - 1; i >= 0; i--){
    2. ret = Add(tmp[i], ret);
    3. }

    到这里我们的整体布局已经完成了,接下来就该实现 alongMultiply() 方法了:

    1. public String alongMultiply(String s, char t){
    2. String ret = ""; //用来存储最后的返回值
    3. if (s.charAt(0) == '0' || t == '0'){
    4. return "0";
    5. }
    6. int tt = t - '0';
    7. int ten = 0; //用来存储每次的进位
    8. for (int i = s.length() - 1; i >= 0; i--){
    9. int tmp = s.charAt(i) - '0';
    10. tmp *= tt;
    11. tmp += ten;
    12. ten = tmp / 10;
    13. ret += tmp % 10;
    14. }
    15. if (ten != 0){
    16. ret += ten;
    17. }
    18. return ret;
    19. }

     Add() 方法的实现:

    1. public String Add(String a, String b){
    2. String str = ""; //存储最终的返回值
    3. int aLen = a.length() - 1;
    4. int ai = 0;
    5. int bLen = b.length() - 1;
    6. int bi = 0;
    7. int ten = 0; //用来存储每次的进位
    8. while(aLen >= ai && bLen >= bi){
    9. int tmp = (a.charAt(ai++) - '0') + (b.charAt(bi++) - '0');
    10. tmp += ten;
    11. ten = tmp / 10;
    12. str += tmp % 10;
    13. }
    14. while(aLen >= ai){
    15. int tmp = a.charAt(ai++) - '0';
    16. tmp += ten;
    17. ten = tmp / 10;
    18. str += tmp % 10;
    19. }
    20. while(bLen >= bi){
    21. int tmp = b.charAt(bi++) - '0';
    22. tmp += ten;
    23. ten = tmp / 10;
    24. str += tmp % 10;
    25. }
    26. if (ten != 0){
    27. str += ten;
    28. }
    29. return str;
    30. }

    接下来我们只要再将最终的值进行反转本题就算做完了:

    1. StringBuffer stringBuffer = new StringBuffer();
    2. for (int i = ret.length() - 1; i >= 0; i--){
    3. stringBuffer.append(ret.charAt(i));
    4. }
    5. ret = stringBuffer.toString();

     当然你也可以用(我用上面的方法主要是因为它比较快):

    1. tmp[0] = ret;
    2. ret = "";
    3. for (int i = tmp[0].length() - 1; i >= 0; i--){
    4. ret += tmp[0].charAt(i);
    5. }

  • 相关阅读:
    设计模式详解(十二)——外观模式
    1024节日快乐
    毕业设计-基于机器视觉的颜色目标识别
    28个团队建设游戏
    常见的Java上机面试题
    Redis哨兵集群搭建
    使用NRM管理Node镜像源,提升包下载速度
    Linux信号量(简易版)
    A-Level商务例题解析及练习Income Statement
    【MyBatis笔记07】MyBatis中的批量操作(批量新增、批量删除、批量更新)
  • 原文地址:https://blog.csdn.net/2302_76339343/article/details/132737248