今天是2020年4月14日,星期二。
題目描述
給你兩個 非空 鏈表來代表兩個非負整數。數字最高位位於鏈表開始位置。它們的每個節點只存儲一位數字。將這兩數相加會返回一個新的鏈表。
你可以假設除了數字 0 之外,這兩個數字都不會以零開頭。
進階:
如果輸入鏈表不能修改該如何處理?換句話說,你不能對列表中的節點進行翻轉。
示例:
輸入:(7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)
輸出:7 -> 8 -> 0 -> 7
題目思路
看到這兩個鏈表後,可以想到將每個鏈表轉化爲一個數字,進而將兩個鏈表的相加轉化爲兩個數字的加和。但在Java中存在一個問題,如果鏈表很長,可能轉換爲數字後,其範圍大於了int最大的表示範圍,甚至超過了long類型,此時就會出現問題,說明在大範圍數據的時候不適用。後面借用了List去存儲了鏈表中的數據,進行了求和,但是這個方法還是比較低效。
高效一些的方法則是可以藉助棧的特性,遍歷每個鏈表並加入棧中,則"高位"的數字位於棧底,最後相加;"低位"的數字位於棧頂,先相加。最後轉換爲結果需要的list即可。
參考代碼
- 自己寫的低效代碼
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
int length1 = 0;
int length2 = 0;
ListNode tmp1 = l1;
ListNode tmp2 = l2;
List<Integer> value1List = new ArrayList<>();
List<Integer> value2List = new ArrayList<>();
while (tmp1 != null) {
length1++;
value1List.add(tmp1.val);
tmp1 = tmp1.next;
}
while (tmp2 != null) {
length2++;
value2List.add(tmp2.val);
tmp2 = tmp2.next;
}
int min = Math.min(length1, length2);
int max = Math.max(length1, length2);
List<Integer> list = new ArrayList<>();
boolean isJinWei = false;
int index = 0;
if (min == length1) {
for (int i = min - 1, j = max - 1; i >= 0; i--, j--) {
int current = value1List.get(i) + value2List.get(j);
if (isJinWei) {
current += 1;
isJinWei = false;
}
if (current >= 10) {
current -= 10;
isJinWei = true;
}
list.add(index, current);
index++;
}
for (int i = max - min - 1; i >= 0; i--) {
int current = value2List.get(i);
if (isJinWei) {
current++;
isJinWei = false;
}
if (current >= 10) {
current -= 10;
isJinWei = true;
}
list.add(index, current);
index++;
}
if (isJinWei) {
list.add(1);
}
} else {
for (int i = min - 1, j = max - 1; i >= 0; i--, j--) {
int current = value1List.get(j) + value2List.get(i);
if (isJinWei) {
current += 1;
isJinWei = false;
}
if (current >= 10) {
current -= 10;
isJinWei = true;
}
list.add(index, current);
index++;
}
for (int i = max - min - 1; i >= 0; i--) {
int current = value1List.get(i);
if (isJinWei) {
current++;
isJinWei = false;
}
if (current >= 10) {
current -= 10;
isJinWei = true;
}
list.add(index, current);
index++;
}
if (isJinWei) {
list.add(1);
}
}
ListNode head = new ListNode(-1);
for (int i = 0; i < list.size(); i++) {
ListNode node = new ListNode(list.get(i));
node.next = head.next;
head.next = node;
}
return head.next;
}
- 參考甜姨的stack法的實例代碼
/**
* 使用棧的特性存儲數據
*
* @param l1
* @param l2
* @return
*/
public ListNode addTwoNumbers2(ListNode l1, ListNode l2) {
Stack<Integer> stack1 = new Stack<>();
Stack<Integer> stack2 = new Stack<>();
while (l1 != null) {
stack1.push(l1.val);
l1 = l1.next;
}
while (l2 != null) {
stack2.push(l2.val);
l2 = l2.next;
}
int carry = 0;
ListNode head = null;
while (!stack1.isEmpty() || !stack2.isEmpty() || carry > 0) {
int value1 = stack1.isEmpty() ? 0 : stack1.pop();
int value2 = stack2.isEmpty() ? 0 : stack2.pop();
int result = value1 + value2 + carry;
ListNode node = new ListNode(result % 10);
node.next = head;
head = node;
carry = result / 10;
}
return head;
}