LeetCode第二题两数相加解法
LeetCode第二题两数相加解法
/** * LeetCode第二题两数相加解法 * * 描述: 整理LeetCode第二题两数相加 * * @author lyn * @date 2022/4/2 18:52 */public class AddTwoNumbers { public static void main(String[] args) { //1 准备测试数据 String data = "00009"; char[] chars = data.toCharArray(); ListNode node1 = charsAscToListNode(chars); ListNode node2 = new ListNode(8); node2.next=node1; //2 两数相加 ListNode node = addTwoNumbersV4(node1, node1); //3 打印单向链表 StringBuilder builder = listNodeToStr(node); System.out.println(builder); } /** * 版本:v4 * 优点:较v3 省略过多的判断 * 缺陷: 如果递归两个单向链表时就可直接相加并填充 * @param l1 * @param l2 * @return */ public static ListNode addTwoNumbersV4(ListNode l1, ListNode l2) { //1 将单向链表转成char数组 char[] v1Chars =listNodeToChars(l1); char[] v2Chars = listNodeToChars(l2); int carry = 0; int max = Math.max(v1Chars.length, v2Chars.length); //2 数字直接相加时填充单向链表 ListNode head =new ListNode(0); ListNode dummy = head; for (int i = 0; i < max; i++) { char num2 = '0'; if (i < v2Chars.length) { num2 = v2Chars[i]; } char num1 = '0'; if (i < v1Chars.length) { num1 = v1Chars[i]; } int val = num1 + num2 - 96 + carry; int temp = val; val = val % 10; carry = temp / 10; dummy.next=new ListNode(val); dummy=dummy.next; } if (carry != 0) { dummy.next=new ListNode(carry); } return head.next; } /** * 打印单向链表 {将单向链表,转成 字符数组(正序)} * @param chars * @return */ public static char[] listNodeToChars(ListNode node){ StringBuilder result = new StringBuilder(); getNextList(result,node); return result.toString().toCharArray(); } /** * 递归获取单向链表 * @param builder * @param next * @return */ public static ListNode getNextList(StringBuilder builder, ListNode next) { if (next.next == null) { builder.append(next.val); return null; } builder.append(next.val); return getNextList(builder, next.next); } /** * 版本:v3 * 优点:较v2 两数相加时直接填充单向链表 * 缺陷: 填充判断过于繁琐(写完以后我都看不懂,当时主要为了正序填充单向链表和避免bug,加的判断) * @param l1 * @param l2 * @return */ public static ListNode addTwoNumbersV3(ListNode l1, ListNode l2) { //1 将单向链表转成char数组 char[] v1Chars =listNodeToChars(l1); char[] v2Chars = listNodeToChars(l2); //2 数字直接相加时填充单向链表 int carry = 0; int max = Math.max(v1Chars.length, v2Chars.length); ListNode root = new ListNode(); ListNode tempAddress = null; for (int i = 0; i < max; i++) { char num2 = '0'; if (i < v2Chars.length) { num2 = v2Chars[i]; } char num1 = '0'; if (i < v1Chars.length) { num1 = v1Chars[i]; } int val = num1 + num2 - 96 + carry; int temp = val; val = val % 10; carry = temp / 10; if (i == 0) { root.val = val; tempAddress = new ListNode(); root.next = tempAddress; } else { tempAddress.val = val; if (i < (max - 1)) { tempAddress.next = new ListNode(); tempAddress = tempAddress.next; } } } if (carry != 0) { if (max==1){ root.next.val=carry; }else { tempAddress.next = new ListNode(); tempAddress.next.val = carry; } }else if (max==1){ root.next=null; } return root; } /** * 版本:v2 * 优点:较v1 省略了字符串反转,去掉BigDecimal API的使用 * 缺陷: 两数相加时还需要通过StringBuilder中转填充单向链表 * @param l1 * @param l2 * @return */ public static ListNode addTwoNumbersV2(ListNode l1, ListNode l2) { //1 将单向链表转成char数组 char[] v1Chars =listNodeToChars(l1); char[] v2Chars = listNodeToChars(l2); //2 数字直接相加,并进位 int carry = 0; int max = Math.max(v1Chars.length, v2Chars.length); StringBuilder v4 = new StringBuilder(); for (int i = 0; i < max; i++) { char num2 = '0'; if (i < v2Chars.length) { num2 = v2Chars[i]; } char num1 = '0'; if (i < v1Chars.length) { num1 = v1Chars[i]; } int val = num1 + num2 - 96 + carry; int temp = val; val = val % 10; carry = temp / 10; v4.append(val); } if (carry != 0) { v4.append(carry); } //v4 000081 char[] chars = v4.toString().toCharArray(); //4 正序填充单向链表(v2) ListNode node = charsAscToListNodeV2(chars); return node; } /** * 正序填充单向链表(v2) * @param chars * @return */ public static ListNode charsAscToListNodeV2(char[] chars){ ListNode node = null; for (int i = chars.length - 1; i >= 0; i--) { int val = chars[i] - '0'; ListNode up = new ListNode(val); up.next=node; node = up; } return node; } /** * 版本:v1 * 缺陷: leetCode不支持BigDecimal(未通过) * @param l1 * @param l2 * @return */ public static ListNode addTwoNumbersV1(ListNode l1, ListNode l2) { //1 将单向链表转成数字字符串 StringBuilder v1 = listNodeToStr(l1); StringBuilder v2 = listNodeToStr(l2); //2 反转数字 BigDecimal vv1 =new BigDecimal(v1.reverse().toString()); BigDecimal vv2 = new BigDecimal(v2.reverse().toString()); //3 两数相加 BigDecimal result = vv1 .add(vv2) ; char[] chars = ("" + result).toCharArray(); //4 逆向填充单向链表 return charsDescToListNode(chars); } /** * 正序填充单向链表(v1) * @param chars * @return */ public static ListNode charsAscToListNode(char[] chars){ ListNode head=new ListNode(); ListNode node=head; for (int i = 0; i < chars.length; i++) { int num=chars[i]-'0'; node.next=new ListNode(num); node=node.next; } return head.next; } /** * 逆序填充单向链表 * @param chars * @return */ public static ListNode charsDescToListNode(char[] chars){ ListNode node=null; for (int i = 0; i < chars.length; i++) { int num= chars[i]-'0'; ListNode up = new ListNode(num); up.next=node; node=up; } return node; } /** * 打印单向链表 {将单向链表,转成 StringBuilder(正序)} * @param chars * @return */ public static StringBuilder listNodeToStr(ListNode node){ StringBuilder result = new StringBuilder(); getNextList(result,node); return result; } }
实体类
public class ListNode { int val; ListNode next; public ListNode() { } ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } }