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;
    }

}

 

参考资料地址1: 链表的Java实现以及创建链表,链表逆序

posted @ 2022-04-03 23:58  进击的小蔡鸟  阅读(36)  评论(0编辑  收藏  举报