面試題 02.05. 鏈表求和
1、題目描述
-
給定兩個用鏈表表示的整數,每個節點包含一個數位。
-
這些數位是反向存放的,也就是個位排在鏈表首部。
-
編寫函數對這兩個整數求和,並用鏈表形式返回結果。
試題鏈接:https://leetcode-cn.com/problems/sum-lists-lcci/
2、java題解一(未通過):
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode pCurrent = l1;
//遍歷
int index = 0;
int num1 = 0;
while(pCurrent != null) {
int num = pCurrent.val; //個、十、百依次
num1 += num * Math.pow(10,index);
index++;
pCurrent = pCurrent.next;
}
//重復
pCurrent = l2;
index = 0;
int num2 = 0;
while(pCurrent != null) {
int num = pCurrent.val; //個、十、百依次
num2 += num * Math.pow(10,index);
index++;
pCurrent = pCurrent.next;
}
//進行相加
int sum = num1 + num2;
// System.out.println(sum);
//將數字拆分,轉換為鏈表 912 2 91 1 9 9 0
ListNode listNode = new ListNode(sum % 10);
sum = sum / 10;
pCurrent = listNode;
while (sum != 0) {
int x = sum % 10;
pCurrent.next = new ListNode(x);
pCurrent = pCurrent.next;
sum = sum / 10;
}
return listNode;
}
測試結果:
因為測試數值較大,int類型無法正確的進行保存,故出現了錯誤。將int類型改為long類型,在進行測試。
發現所測試的數據遠遠比我們想想的大,因此我們得另辟蹊徑。
3、java題解二
考慮到該算法有超大規模的測試數據,我們引入了BigInteger這個類,來進行測試。
import java.math.BigInteger;
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode pCurrent = l1;
//遍歷
String num1 = "";
while(pCurrent != null) {
int num = pCurrent.val; //個、十、百依次
num1 += num;
pCurrent = pCurrent.next;
}
//重復
pCurrent = l2;
String num2 = "";
while(pCurrent != null) {
int num = pCurrent.val; //個、十、百依次
num2 += num;
pCurrent = pCurrent.next;
}
//逆序遍歷,進行相加
String newNum1 = "";
for(int i = 0;i < num1.length();i++) {
newNum1 += num1.charAt(num1.length() - 1 - i);
}
String newNum2 = "";
for(int i = 0;i < num2.length();i++) {
newNum2 += num2.charAt(num2.length() - 1 - i);
}
// System.out.println(newNum1);
// System.out.println(newNum2);
BigInteger bigInteger1 = new BigInteger(newNum1);
BigInteger bigInteger2 = new BigInteger(newNum2);
BigInteger sum = bigInteger1.add(bigInteger2);
String sumStr = sum.toString();
ListNode saveNode = new ListNode(sumStr.charAt(sumStr.length() - 1) - 48);
pCurrent = saveNode;
for(int i = 1;i < sumStr.length();i++) {
pCurrent.next = new ListNode(sumStr.charAt(sumStr.length() - 1 - i) - 48);
pCurrent = pCurrent.next;
}
return saveNode;
}
}
測試結果:
可以看到,該算法的用時較長,且如果改寫成C語言代碼時,我們並沒有BigInteger這個類。
4、java題解三
對此,我們像將鏈表拆分,引入對位相加的計算策略。
ListNode list = new ListNode(-1); //定義輸出鏈表
ListNode p = list;
int num = 0; //進位數字
int x = 0; //記錄l1鏈表的值
int y = 0; //記錄12鏈表的值
//遍歷兩個鏈表
while(l1 != null ||l2 != null) {
x = l1 == null ? 0 : l1.val;
y = l2 == null ? 0 : l2.val;
int sum = x + y + num;
if(sum < 10) {
p.next = new ListNode(sum);
num = 0;
}else {
p.next = new ListNode(sum % 10);
num = sum / 10;
}
if(l1 != null) l1 = l1.next;
if(l2 != null) l2 = l2.next;
p = p.next;
}
if (num != 0) p.next = new ListNode(num);
return list.next;
測試結果:
可以看到,對於該算法,在java中的運行效率還是可以的。
5、C語言題解
struct ListNode* list = (struct ListNode*)malloc(sizeof(struct ListNode));
list->val = -1; //定義輸出鏈表
list->next = NULL;
struct ListNode* p = list;
int num = 0; //進位數字
int x = 0; //記錄l1鏈表的值
int y = 0; //記錄12鏈表的值
//遍歷兩個鏈表
while(l1 != NULL ||l2 != NULL) {
x = l1 == NULL ? 0 : l1->val;
y = l2 == NULL ? 0 : l2->val;
int sum = x + y + num;
if(sum < 10) {
struct ListNode* temp = (struct ListNode*)malloc(sizeof(struct ListNode));
temp->val = sum;
temp->next = NULL;
p->next = temp;
num = 0;
}else {
struct ListNode* temp = (struct ListNode*)malloc(sizeof(struct ListNode));
temp->val = sum % 10;
temp->next = NULL;
p->next = temp;
num = sum / 10;
}
if(l1 != NULL) l1 = l1->next;
if(l2 != NULL) l2 = l2->next;
p = p->next;
}
if (num != 0) {
struct ListNode* temp = (struct ListNode*)malloc(sizeof(struct ListNode));
temp->val = num;
temp->next = NULL;
p->next = temp;
}
return list->next;
測試結果:
可以看到,在C語言中,該算法的計算效率偏低。