トピック
2つの非負の整数を表す、2つの空でないリンクリストを提供します。番号の最上位ビットは、リンクリストの先頭にあります。それぞれのノードは1桁しか格納しません。これらの2つの数値を追加すると、新しいリンクリストが返されます。
数値0を除いて、これら2つの数値はどちらもゼロで始まらないと想定できます。
上級:
入力リンクリストを変更できない場合はどうすればよいですか?つまり、リスト内のノードを反転することはできません。
例:
输入:(7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4) 输出:7 -> 8 -> 0 -> 7
構文解析
この質問の混乱の1つのポイントは、入力リストを結果として再利用する必要があるかどうかです。再利用する場合は、キャリーの問題に対処するための結果リストがあります。再利用しない場合は、ノードを直接作成すると大幅に削減されます。不利な点は、より多くのスペースを占めることです。
考える最も簡単な方法は、フリップして追加してからフリップすることです。反転が許可されていない場合は、スペースを利用し、補助配列、長いリンクリストの長さを使用して、リンクリストのキャリーを処理し、結果を出力できます。3番目のタイプは、トピック設定を使用した逆処理です。つまり、スタック、最初の入力と出力です。
解決策1:配列を助長し、入力リンクリストを再利用すると、時間とスペースが非常に効果的です
class Solution {
int cntNodes(ListNode* list) {
if (NULL == list)
return 0;
int len = 0;
while (list) {
++len;
list = list->next;
}
return len;
}
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
if (NULL == l1)
return l2;
if (NULL == l2)
return l1;
//l1指向长链表
int len1 = cntNodes(l1);
int len2 = cntNodes(l2);
if (len1 < len2) {
swap(l1, l2);
swap(len1, len2);
}
//tmp存两个数的和
vector<int> tmp(len1);
ListNode *p = l1;
for (int i = 0; i < len1; ++i) {
tmp[i] = p->val;
p = p->next;
}
p = l2;
for (int i = len1-len2; i < len1; ++i) {
tmp[i] += p->val;
p = p->next;
}
//处理进位
int chg = 0;
for (int i = len1-1; i >= 0; --i) {
tmp[i] = tmp[i]+chg;
chg = tmp[i]/10;
tmp[i] = tmp[i]%10;
}
//将数存入长链表
p = l1;
for (int i = 0; i < len1; ++i) {
p->val = tmp[i];
p = p->next;
}
if (chg) {
ListNode* node = new ListNode(chg);
node->next = l1;
return node;
}
return l1;
}
};
空間はO(max(m、n))、時間はO(m + n)
解決策2:入力リンクリストを再利用する代わりにスタックを使用する
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
if (NULL == l1)
return l2;
if (NULL == l2)
return l1;
//链表入栈
stack<int> sta1;
stack<int> sta2;
ListNode *p = l1;
while (p) {
sta1.push(p->val);
p = p->next;
}
p = l2;
while (p) {
sta2.push(p->val);
p = p->next;
}
//节点出栈
ListNode dummy(0);
ListNode *node = &dummy;
int chg = 0;
while (!sta1.empty() || !sta2.empty()) {
int num = 0;
if (!sta1.empty()) {
num = sta1.top();
sta1.pop();
}
if (!sta2.empty()) {
num += sta2.top();
sta2.pop();
}
num += chg;
chg = num/10;
num %= 10;
p = new ListNode(num);
p->next = node->next;
node->next = p;
}
if (chg) {
p = new ListNode(chg);
p->next = node->next;
node->next = p;
}
return dummy.next;
}
};
スタック時間の複雑さで言われる解釈はO(max(m、n) )(なぜ私はそれがO(m + n)だと思うのか、それなら2つのスタックの圧力ではなく、ああを横断するためのプッシュと見なすことができます.. 。)、スペースはO(m + n)です。入力リンクリストを再利用すると、多くの作業が発生します。それはあなたがそれをどのように実現するかに依存します。