LeetCode2 两数相加-最好时间复杂度O(1)的解法

78 阅读2分钟

1. 题目

两数相加 给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。   示例 1:

输入: l1 = [2,4,3], l2 = [5,6,4]
输出: [7,0,8]
解释: 342 + 465 = 807.

示例 2:

输入: l1 = [0], l2 = [0]
输出: [0]

2. 思路

这一题名为两数相加,其实是考察链表,两个链表之间的合并。 处理处理链表的要点: (1)注意指针 (2)巧用哨兵节点来简化逻辑

算法要从时间和空间复杂度来考虑, 这里的思路和通常的有所不同。 (1)空间上,合并完就得两个链表就不用了,不如我们不去创建新的链表,能省就省,旧瓶装新酒,直接用原来链表里的对象。 (2)时间上,假设短的链表长度为m,那么再合并完m对个节点后,又没有进位的话,后续的合并逻辑似乎也没必要执行了,直接指针指到剩下节点的开头。

3. 解题方法

结合代码的注释吧

4. 复杂度

这里的解法和其它不太一样,假设长的链表长度为n,短的链表长度为m。

其它一些算法空间复杂度是O(n),时间复杂度是O(n)。

而本算法复杂度分析如下:

时间复杂度:

最好时间复杂度为:O(1)O(1)

最差时间复杂度为:O(n)O(n)

较大概率一般情况的下时间复杂度为:O(m)O(m)

空间复杂度

O(1)O(1)

5. Code

/**
 * 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) {
    	// 如果有一个链表为空,则没有必要继续合并了,直接返回另外一个链表
    	if (l1 == null) {
			return l2;
		}
    	if (l2 == null) {
			return l1;
		}
    	// 哨兵节点,简化编程,head将作为该函数返回的链表的头节点
    	ListNode node = new ListNode(-1);
    	ListNode head = node;
    	int c = 0;
    	while(l1 != null && l2 != null) {
    		c = l1.val + l2.val + c;
    		// 复用l1链表里的对象
    		l1.val = c % 10;
    		c = c / 10;
    		node.next = l1;
    		node = l1;
    		
    		l1 = l1.next;
    		l2 = l2.next;
    	}
    	// l1 长于l2,并且还有进位
    	while(l1 != null && c!=0) {
    		c = l1.val + c;
    		l1.val = c % 10;
    		c = c/10;
    		node.next = l1;
    		node = l1;
    		
    		l1 = l1.next;
    	}
    	// l2长于l1, 
    	if (l2 != null) {
		node.next = l2;
	}
    	while(l2 != null && c!=0) {
    		// l2 仍然有未遍历到的节点,并且有进位
    		c = l2.val + c;
    		// 复用l2链表里的对象
    		l2.val = c % 10;
    		c = c / 10;
    		node.next = l2;
    		node = l2;
    		
    		l2 = l2.next;
    	}
    	// 处理最后的进位
    	if (c != 0) {
    		node.next = new ListNode(c);
		}
		return head.next;   
    }
}