大家好,我是LvZi,今天带来
笔试狂刷--Day2(模拟高精度算法)
一.二进制求和
题目链接:二进制求和
分析:
代码实现:
class Solution {
public String addBinary(String a, String b) {
int c1 = a.length() - 1, c2 = b.length() - 1, t = 0;
StringBuffer ret = new StringBuffer();
while(c1 >=0 || c2 >= 0 || t != 0) {
if(c1 >= 0) t += a.charAt(c1--) - '0';// 保证不为空
if(c2 >= 0) t += b.charAt(c2--) - '0';// 保证不为空
char ch = (char)((t % 2) + '0');
ret.append(ch);
t /= 2;// 存储进位
}
return ret.reverse().toString();
}
}
二.大数相加(十进制求和)
大数相加(十进制求和)
代码实现:
1.模拟
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 计算两个数之和
* @param s string字符串 表示第一个整数
* @param t string字符串 表示第二个整数
* @return string字符串
*/
public String solve (String a, String b) {
// write code here
int c1 = a.length() - 1, c2 = b.length() - 1, t = 0;
StringBuffer ret = new StringBuffer();
while(c1 >=0 || c2 >= 0 || t != 0) {
if(c1 >= 0) t += a.charAt(c1--) - '0';// 保证不为空
if(c2 >= 0) t += b.charAt(c2--) - '0';// 保证不为空
char ch = (char)((t % 10) + '0');
ret.append(ch);
t /= 10;// 存储进位
}
return ret.reverse().toString();
}
}
2.使用Java内置的BigInteger
import java.util.*;
import java.math.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 计算两个数之和
* @param s string字符串 表示第一个整数
* @param t string字符串 表示第二个整数
* @return string字符串
*/
public String solve (String s, String t) {
// write code here
BigInteger a = new BigInteger(s);
BigInteger b = new BigInteger(t);
BigInteger ret = a.add(b);
return ret.toString();
}
}
三.大数乘法
大数乘法
分析:
代码实现:
1.
import java.util.*;
import java.math.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串 第一个整数
* @param t string字符串 第二个整数
* @return string字符串
*/
public String solve (String ss, String tt) {
// write code here
char[] s = new StringBuffer(ss).reverse().toString().toCharArray();
char[] t = new StringBuffer(tt).reverse().toString().toCharArray();
int n = s.length, m = t.length;
int[] tmp = new int[m + n];
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
tmp[i + j] += (s[i] - '0') * (t[j] - '0');
// 模拟加法
int c = 0;
StringBuffer ret = new StringBuffer();
for(int x : tmp) {
c += x;
ret.append((char)(c % 10 + '0'));
c /= 10;
}
// 处理前导零
while(ret.length() > 1 && ret.charAt(ret.length() - 1) == '0') {
ret.deleteCharAt(ret.length() - 1);
}
return ret.reverse().toString();
}
}
2.使用BigInteger
import java.util.*;
import java.math.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串 第一个整数
* @param t string字符串 第二个整数
* @return string字符串
*/
public String solve (String s, String t) {
// write code here
BigInteger a = new BigInteger(s);
BigInteger b = new BigInteger(t);
BigInteger ret = a.multiply(b);
return ret.toString();
}
}
四.两数相加I(链表)
题目链接:两数相加I
代码实现:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode cur1 = l1;
ListNode cur2 = l2;
ListNode phead = new ListNode(0);
ListNode cur = phead;// 用于尾插
int t = 0;// 用于表示本次相加的结果 处理进位
// 要注意t最后可能不为0 要进一位
while(cur1 != null || cur2 != null || t != 0) {
// 加上第一个节点
if(cur1 != null) {
t += cur1.val;
cur1 = cur1.next;
}
// 加上第二个节点
if(cur2 != null) {
t += cur2.val;
cur2 = cur2.next;
}
ListNode newNode = new ListNode(t % 10);
t /= 10;
// 尾插
cur.next = newNode;
cur = newNode;
}
return phead.next;
}
}
五.两数相加II(链表逆序)
题目链接:两数相加II(链表逆序)
代码实现:
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* public ListNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head1 ListNode类
* @param head2 ListNode类
* @return ListNode类
*/
public ListNode addInList (ListNode head11, ListNode head22) {
// write code here
ListNode h1 = reverse(head11), h2 = reverse(head22), ret = new ListNode(0), phead = ret;
ListNode c1 = h1, c2 = h2;
int t = 0;
while (c1 != null || c2 != null || t != 0) {
if (c1 != null) {
t += c1.val;
c1 = c1.next;
}
if (c2 != null) {
t += c2.val;
c2 = c2.next;
}
ListNode tmp = new ListNode(t % 10);
t /= 10;
phead.next = tmp;
phead = phead.next;
}
// 逆序最后的结果
return reverse(ret.next);
}
// 逆序链表
private ListNode reverse(ListNode head) {
ListNode phead = new ListNode(0), cur = head;
while (cur != null) {
ListNode curNext = cur.next;
cur.next = phead.next;
phead.next = cur;
cur = curNext;
}
return phead.next;
}
}
总结:
- 高精度算法本质上就是
模拟竖式运算
,高精度加法通过变量t
和进制来确定每次相加的结果和保存响应的进位;高精度乘法实际上是模拟了无进位相乘再相加
的过程,使用数组保存当前位置结果的总和,最后再对整个数组模拟十进制相加即可(注意可能的前导0) - 注意模拟过程中的顺序,需要从
最低位
开始模拟,以及注意最后的返回结果(有的需要逆序) - 在Java中,如果涉及到高进度的加减法,可以使用自带的
BigInteger
类