“两个数字相加”问题是您在 LeetCode 等各种编码挑战网站上都会发现的常见问题。这个问题很好地介绍了如何使用链接列表,并且需要使用两个链接列表来创建第三个列表。为了解决此类问题,在深入研究代码之前考虑一下如何在纸上解决它会很有帮助。
问题陈述
给您两个表示两个非负整数的非空链表。数字以相反的顺序存储,每个节点包含一个数字。将两个数字相加并以链表形式返回总和。
您可以假设这两个数字不包含任何前导零,除了数字 0 本身。
例子:
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.
方法
问题表明数字以相反的顺序存储。这让我停顿了一分钟;然而,它实际上使解决这个问题变得更容易。如果我们在纸上写下两个数字相加的问题,我们就会以相反的顺序将它们相加。
// To add these numbers we would start from the
// right side (in reverse order)
342
+465
----
807
思考如何将两个数字加在一起可以帮助我们想出一种算法来解决这个问题。只需迭代两个列表并将每个数字相加(模拟从右侧开始)即可。如果一个数字有更多位数,我们很有可能必须检查是否为空。而且,如果两个数字之和大于 9,我们还必须处理结转。有关更多详细信息,请参阅下面代码中的注释。
/**
-
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; }
}
/* -
Solution
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
// Head of the new Linked List - this will be the result
ListNode result = new ListNode();
// Reference of the result, which is empty at this point
ListNode pointer = result;
// Carry over number
int carry = 0;while(l1 != null || l2 != null) { // if either value is null, use zero else use value int x = l1 == null ? 0 : l1.val; int y = l2 == null ? 0 : l2.val; // do the adding int sum = x + y + carry; // calculate the carryover. Remember this is // integer division and will only return whole // numbers. carry = sum / 10; // At this point we add the total sum mod 10 to // the new node in the results list. If the // integer is greater than 10 this will return // the remainder. If its less than 10, it will // return the integer. pointer.next = new ListNode(sum % 10); pointer = pointer.next; // Move to next node if (l1 != null) { l1 = l1.next; } if (l2 != null) { l2 = l2.next; } } // After the last iteration, check to see if there is // a carryover left, if so, add it to the results // list if (carry != 0) { pointer.next = new ListNode(carry); } return result.next;
}
}
复杂
现在我们可以计算出解决方案的复杂性。
时间复杂度
l1如果is的长度和ism的长度,则上面的解决方案将迭代 m 或 n 次。这给出了O(max(m, n))的时间复杂度。l2n
空间复杂度
O(max(m, n)),因为我们正在创建一个新的链表来返回。
最后的想法
通过思考如何将两个数字加在一起,您可以想出一种算法来处理此类问题。在某些情况下,可以通过思考如何解决“现实生活”中的问题而不是使用编程语言来找到初步解决方案。这就是为什么代码挑战专家建议在进入实际代码之前使用纸张和 sudo 代码解决问题的原因之一。这种技术可以帮助您思考问题本身而不是实现。上述解决方案只是解决该问题的一种方法。