本身写一个函数,求两个大数相加之和【大厂面试干货】

前段时间,有幸参加了某钉的一个在线代码测评,其中有一个算法题颇有意思,题目为:git

//评测题目: 无// 大数加法// 实现一个函数,输入两个大整数字符串,计算两数之和,用字符串表达。// 用例一://   输入:"12345", "123"//   输出:"12468"// 用例二://   输入:"12345", "-123"//   输出:"12222"// 用例三://   输入:"12345", "-12345"//   输出:"0"// 用例四://   输入:"-12345", "123"//   输出:"-12222"// 用例五://   输入:"1111111111111111"(16位1), "2222222222222222" (16位2)//   输出:"3333333333333333"(16位3)// 确保以上测试用例正确。

 

我初一看,这道题太简单不过了,因而三下五除二,一分钟就给他敲完了,实现以下:程序员

public class BigDigitalUtil {public static String digitialAdd(String a,String b){BigDecimal digital1 = BigDeciaml.valueOf(a);BigDecimal digital2 = BigDeciaml.valueOf(b);return digital1.add(digital2).toString();    }}public class TestBigDigitalAdd() {public static void main(String[] args) {String a = "12345";String b = "123";        System.out.println(BigDigitalUtil.digitialAdd(a,b));}}

 

这时候测评人跟我说,这么写不能说我错,可是他的初衷是但愿本身能实现这个算法,相似于本身实现BigDecimal的add方法。算法

 

因而,我开始从新审视这套题。首先是要求两个大数相加,这个时候咱们就不能直接用int类型了,由于都知道int类型可表示的整数有限。其次又不能借助Java自带的相似BigDecimal这样的函数,怎么办呢?又默念一遍存在即合理,既然有这道题的诞生,那么必定能够解。数组

 

这时候,我突然想到我我的自认为“万能”的String类型,咱们能够把整数变成字符串啊,用字符串来表示大数,这样就能够实现大数相加了,整理了一下思路,主要要解决如下几个问题:app

 

  1. 咱们小学就学过加减法,都是从个位数开始加减的,可是对于长度可能不一样的字符串,咱们无法从第一位开始相加,只有从最后一位开始相加,因而,我要先将字符砖翻转过来。函数

  2. 翻转之后,要怎么解决进位问题呢?还有可能和的位数也要进一的,这时候想到能够把字符串短的那个前面高位都用”0”表示,这样就方便一位一位的相加啦。测试

  3. 最后把得出来的值再翻转过来就行了。ui

  4. 看到题目,若是其中有个大数是负数怎么办?既然前三步都能作出来,那负数是否是也能够变成正数来计算呢?code

 

好了,既然思路理清楚了,那咱们废话就很少说了,最后实现代码以下:blog













package com.weiya.mazhichu.designpatterns.decorator;/*** <p class="detail">* 功能: 大数加法,实现一个函数,输入两个大整数字符串,计算两数之和,用字符串表达。* </p>** @author Moore* @ClassName Big digital util.* @Version V1.0.* @date 2019.06.12 21:43:18*/public class BigDigitalUtil {//评测题目: 无// 大数加法// 实现一个函数,输入两个大整数字符串,计算两数之和,用字符串表达。// 用例一://   输入:"12345", "123"//   输出:"12468"// 用例二://   输入:"12345", "-123"//   输出:"12222"// 用例三://   输入:"12345", "-12345"//   输出:"0"// 用例四://   输入:"-12345", "123"//   输出:"-12222"// 用例五://   输入:"1111111111111111"(16位1), "2222222222222222" (16位2)//   输出:"3333333333333333"(16位3)// 确保以上测试用例正确。/*** 两个大数相加** @param a :* @param b :* @return string* @author Moore* @date 2019.06.12 23:43:42*/public static String bigDigitalAdd(String a, String b) {int aLength = a.length();int bLength = b.length();// 翻转字符串成数组char[] aArray = new StringBuilder(a).reverse().toString().toCharArray();char[] bArray = new StringBuilder(b).reverse().toString().toCharArray();int MAX_LENGTH = aLength > bLength ? aLength : bLength;int[] newArray = new int[MAX_LENGTH + 1];// 按照数位对应相加,判断当前位是否超过了当前数值的最大位数,若是是用0代替进行运算for (int i = 0; i < MAX_LENGTH + 1; i++) {int num1 = i < aLength ? (aArray[i] - '0') : 0;int num2 = i < bLength ? (bArray[i] - '0') : 0;newArray[i] = num1 + num2;}// 处理进位for (int i = 0; i < MAX_LENGTH + 1; i++) {if (newArray[i] > 10) {newArray[i + 1] += newArray[i] / 10;newArray[i] = newArray[i] % 10;}}StringBuilder result = new StringBuilder();//判断是否有前置0,若是有忽略boolean hasZero = true;for (int i = MAX_LENGTH; i >= 0; i--) {if (newArray[i] == 0 && hasZero) {continue;} else {hasZero = false;}// 结果再翻转过来result.append(newArray[i]);}return result.toString();}/*** 两个大数相减(前提:a>b,求a-b)** @param a :* @param b :* @return string* @author Moore* @date 2019.06.12 23:43:42*/public static String bigDigitalSub(String a, String b) {char[] aArray = new StringBuilder(a).reverse().toString().toCharArray();char[] bArray = new StringBuilder(b).reverse().toString().toCharArray();int aLength = aArray.length;int bLength = bArray.length;int MAX_LENGTH = aLength > bLength ? aLength : bLength;int[] newArray = new int[MAX_LENGTH];for (int i = 0; i < MAX_LENGTH; i++) {int num1 = i < aLength ? (aArray[i] - '0') : 0;int num2 = i < bLength ? (bArray[i] - '0') : 0;newArray[i] = num1 - num2;}//若是结果中的某一位小于0,则向高位借位,而后将本位加10for (int i = 0; i < MAX_LENGTH; i++) {if (newArray[i] < 0) {newArray[i + 1] -= 1;newArray[i] += 10;}}StringBuilder result = new StringBuilder();boolean hasZero = false;for (int i = MAX_LENGTH - 1; i >= 0; i--) {if (hasZero == false && newArray[i] == 0) {continue;} else {hasZero = true;}result.append(newArray[i]);}return result.toString();}/*** 比较两个大数的大小,a>b返回1,a小于b返回-1,a=b返回0** @param a :* @param b :* @return int* @author Moore* @date 2019.06.12 23:43:42*/public static int compareTo(String a, String b) {int aLength = a.length();int bLength = b.length();if (aLength > bLength) {return 1;} else if (aLength < bLength) {return -1;} else {int index = 0;while (true) {// 每一个位数比较大小if (a.charAt(index) > b.charAt(index)) {return 1;} else if (a.charAt(index) < b.charAt(index)) {return -1;} else {if (index == aLength - 1) {return 0;}index++;}}}}/*** 求两个大整数之和(正数可为负数)** @param a :* @param b :* @return* @author Moore* @date 2019.06.12 23:43:42*/public static String bigDigitalSum(String a, String b) {String result = null;//若是两个大数都是负数if (a.charAt(0) == '-' && b.charAt(0) == '-') {a = a.substring(1);b = b.substring(1);result = bigDigitalAdd(a, b);result = "-" + result;}//若是两个大数中,一个正数,一个负数else if (a.charAt(0) == '-' || b.charAt(0) == '-') {if (a.charAt(0) == '-') {a = a.substring(1);if (compareTo(a, b) == 1) {result = "-" + bigDigitalSub(a, b);} else if (compareTo(a, b) == -1) {result = bigDigitalSub(b, a);} else {result = "0";}} else {b = b.substring(1);if (compareTo(a, b) == 1) {result = bigDigitalSub(a, b);} else if (compareTo(a, b) == -1) {result = "-" + bigDigitalSub(b, a);} else {result = "0";}}}//两个大数都是正数else {result = bigDigitalAdd(a, b);}return result;}public static void main(String[] args) {System.out.println(bigDigitalSum("12345","123"));System.out.println(bigDigitalSum("12345","-123"));System.out.println(bigDigitalSum("12345","-12345"));System.out.println(bigDigitalSum("-12345","123"));System.out.println(bigDigitalSum("1111111111111111","2222222222222222"));}}

 

查看一下运行结果:

 

是否是很棒棒哒,是否是要爱上本身了,可当我再次看到这题的时候,又发现了一个bug,题目要求输入两个大数,拜托,输入输入,Scanner scanner = new Scanner(System.in);就这样被我吃了,唉,难怪最后我没有过,真是活该!哈哈!

 

经过这个案例,只是想说,在咱们遇到一个需求的时候,必定要先理清楚需求和思路再开始写代码,要记住,咱们不要作一个机器程序员,而是要作一个有思想的程序员,互联网时代万事以结果为导向,注重速度的同时更要保证你交付的每一行代码都有质量,这样咱们创造的产品才能更有生命力。

相关文章
相关标签/搜索