两链表相加问题

目录

一、题目

二、思路一

三、思路二


一、题目

两链表相加问题, 满10向next进1

例如: (4->2->1) +(6->3->7),

得到结果为: 0->6->8

得到结果860

二、思路一

        将链表二中的数据加到链表一上,然后返回链表一,如果链表一的除了末位的满10那么进1。

我们可以给每一个链表中的所有节点放入到一个 Node [] table里, 然后通过fo循环遍历两个table。

        此方式利用牺牲空间的方式初始化2个数组,只用一个for循环就能实现两个链表相加。

    private static SumOfTwoLinkedList addLinkedList(SumOfTwoLinkedList one, SumOfTwoLinkedList two) {
        for (int i = 0; i < one.table.length; i++) {
            if (one.table[i] != null) {
                // 两条链表中对应位置值相加
                Integer sum = (Integer) one.table[i].data + (Integer) two.table[i].data;
                boolean overflow = false;
                if (sum >= 10 && i + 1 <= one.table.length) {
                    // 是否进位
                    overflow = true;
                    // 最后一位不支持进位
                    if (i + 1 == one.table.length) {
                        throw new RuntimeException("illegal params! check lists");
                    }
                    //下一位+1
                    one.table[i + 1].data = (Integer) one.table[i + 1].data + 1;
                }
                if (overflow) {
                    // 当前位归0
                    one.table[i].data = 0;
                    continue;
                }
                one.table[i].data = sum;
            }
        }
        return one;
    }

完整代码

package leetcode100;


/**
 * @decription:
 * @author: zhengbing.zhang
 * @date: 2021/7/12 17:40
 * 两链表相加问题, 满10进1
 * 例如:  (4->2->1) +(6->3->7),
 * 得到结果为: 0->6->8
 * 得到结果860
 * 假设链表的长度是相等的, 不考虑表尾溢出的情况
 */
public class SumOfTwoLinkedList {


    private static SumOfTwoLinkedList addLinkedList(SumOfTwoLinkedList one, SumOfTwoLinkedList two) {
        for (int i = 0; i < one.table.length; i++) {
            if (one.table[i] != null) {
                // 两条链表中对应位置值相加
                Integer sum = (Integer) one.table[i].data + (Integer) two.table[i].data;
                boolean overflow = false;
                if (sum >= 10 && i + 1 <= one.table.length) {
                    // 是否进位
                    overflow = true;
                    // 最后一位不支持进位
                    if (i + 1 == one.table.length) {
                        throw new RuntimeException("illegal params! check lists");
                    }
                    //下一位+1
                    one.table[i + 1].data = (Integer) one.table[i + 1].data + 1;
                }
                if (overflow) {
                    // 当前位归0
                    one.table[i].data = 0;
                    continue;
                }
                one.table[i].data = sum;
            }
        }
        return one;
    }

    public static void main(String[] args) {

        SumOfTwoLinkedList l1 = new SumOfTwoLinkedList();
        SumOfTwoLinkedList l2 = new SumOfTwoLinkedList();
        Node oneHead = new Node(3);
        oneHead.addNode(new Node(7)).addNode(new Node(1));
        Node twoHead = new Node(6);
        twoHead.addNode(new Node(3)).addNode(new Node(6));
//        Node one = new Node(3, new Node(7, new Node(1, null)));
//        Node two = new Node(6, new Node(3, new Node(8, null)));
        l1.initLinkList(oneHead);
        l2.initLinkList(twoHead);
        SumOfTwoLinkedList result = addLinkedList(l1, l2);
        System.out.println(result.traverseLinkList());
    }

    Node[] table;


    /**
     * 初始化链表
     *
     * @param head
     */
    public void initLinkList(SumOfTwoLinkedList.Node head) {
        int index = 0;
        this.table = new Node[head.length()];
        while (head.next != null) {
            this.table[index] = head;
            head = head.next;
            index++;
        }
        this.table[index] = head;
    }

    public String traverseLinkList() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < table.length; i++) {
            Object obj = this.table[i];
            if (obj != null) {
                sb.append(((Node) obj).getData());
                sb.append("->");
            }
        }
        sb.append("NULL");
        return sb.toString();
    }


    static class Node {

        private Object data;

        private Node next;


        public Node(Object data) {
            this.data = data;
        }


        public Node addNode(Node node) {
            this.next = node;
            return node;
        }


        public Object getData() {
            return this.data;
        }

        /**
         * 返回链表长度
         */
        public Integer length() {
            Node current = this;
            int count = 1;
            while (current.next != null) {
                count++;
                current = current.next;
            }
            return count;
        }


        public String traverse() {
            return this.data + "->" + (this.next == null ? "Null" : this.next.traverse());
        }


    }

}


输入:

3——>7——>1——>NULL

6——>3——>6——>NULL

执行结果:

此方式的时间复杂度是o(n), 但是空间复杂度o(m+n),需要利用额外的空间创建LinkedList。
 

三、思路二

        大思路:

        不创建额外的链表,我们只需要一个单链表去接收2个链表节点叠加后的结果, 然后返回新的单链表即可。

         实现原理:
        1) 两个链表相同位置的节点数据相加可能会产生进位,如果尾节点也进位了,那么需要创建新的节点去接收进位。

        2)  如何计算当前位(节点)的值?

        可以用 (x+y) %10 的结果作为当前位的值,但是这样的话要考虑到进位的情况,那么就是(carry+x+y)%10。

        3)  如何判断进位? 

         可以根据 两个节点的和除以10是否等于0来判断,如果两数之和除以10等于0,那么表示没有进位,如果等于1,那么表示产生进位。

        比如:  链表1 中的节点x = 5, 链表2中的节点y=3, x+y/10=0。 这样是不会产生进位的。

由于之前的进位carry会影响到当前位两个节点的累加和,因此需要用(carry+x+y)/10 来判断进位

package leetcode100;

import java.util.List;

/**
 * @decription:
 * @author: zhengbing.zhang
 * @date: 2021/7/20 15:49
 * l1: 4->2->1
 * l2: 6->3->7
 */
public class SumOfTwoLinkedList01 {


    static class ListNode {
        ListNode next;

        Object value;

        public ListNode(ListNode next, Object value) {
            this.next = next;
            this.value = value;
        }

        public ListNode(Object value) {
            this.value = value;
        }


        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(value);
            while (next != null) {
                sb.append("->");
                sb.append(next.value);
                next = next.next;
            }
            return sb.toString();
        }
    }

    public static ListNode addTwoListNodes(ListNode l1, ListNode l2) {
        ListNode dumpHead = new ListNode(0);
        ListNode p = l1, q = l2, curr = dumpHead;
        // 进位
        int carry = 0;
        while (p != null || q != null) {
            int x = p.value == null ? 0 : (int) p.value;
            int y = q.value == null ? 0 : (int) q.value;
            int sum = carry + x + y;
            carry = sum / 10;
            curr.next = new ListNode(sum % 10);
            // 不断叠加curr
            curr = curr.next;
            if (p != null) {
                p = p.next;
            }
            if (q != null) {
                q = q.next;
            }
        }
        if (carry > 0) {
            curr.next = new ListNode(carry);
        }
        // head节点没有存值
        return dumpHead.next;
    }

    public static void main(String[] args) {
        ListNode tail01 = new ListNode(null, 1);
        ListNode node01 = new ListNode(tail01, 2);
        ListNode l1 = new ListNode(node01, 4);

        ListNode tail02 = new ListNode(null, 8);
        ListNode node02 = new ListNode(tail02, 7);
        ListNode l2 = new ListNode(node02, 6);
        ListNode result = addTwoListNodes(l1, l2);
        System.out.println(result);

    }
}

输入:

        l1: 4->2->1

        l2: 6->7->8

打印结果:  0->0->0->1

        此方法的时间复杂度为: o(max(m,n)) 其中m,n为链表的长度。空间复杂度为o(max(m+n))+1, 因为头节点没有存值,占了一个位,由于存next后面的值。 

        如果两链表长度不相等,那么也可以合并成为一个新的节点,因为可以给空节点初始化一个为0的值。

    int x = (p.value == null) ? 0 : (int) p.value;

        

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乌托邦钢铁侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值