今日の質問
逆順の2つの連結リストを下位から加算する必要があり、その結果も逆順に出力され、戻り値は逆順の結果連結リストの先頭ノードとなる。
入力: (2 -> 4 -> 3) + (5 -> 6 -> 4)
出力: 7 -> 0 -> 8
説明: 342 + 465 = 807。
問題解決のアイデア:
さまざまな持ち運び状況に注意が必要です。特殊な場合の例:
入力: (9 -> 9 -> 9 -> 9 -> 9) + (1 -> )出力: 0 - >
0 -> 0 -> 0 -> 0 -> 1
処理方法を統一する場合、最初に仮想ヘッド ノードを作成し、この仮想ヘッド ノードの Next が実際のヘッドを指すようにすることで、ヘッドを
個別に処理する必要がなく、while ループを直接使用できます。また、ループの終了を判断する条件は、p.Next!である必要はありません。= nil であるため、最後の
ビットを追加で計算する必要があり、ループ終了条件は p != nil である必要があります。
サンプルコード:
class addTwoNumbers{
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode* re = new ListNode(0);
ListNode* r = re;
int carry = 0;
while(l1!=NULL || l2!=NULL)
{
int x = 0;
int y = 0;
if(l1!=NULL)
{
x = l1->val;
}else{
x = 0;
}
if(l2!=NULL)
{
y = l2->val;
}else{
y = 0;
}
int s = carry + x + y;
carry = s/10;
r->next = new ListNode(s%10);
r = r->next;
if(l1!=NULL)
{
l1 = l1->next;
}
if(l2!=NULL)
{
l2 = l2->next;
}
}
if(carry > 0){
r->next = new ListNode(carry%10);
}
return re->next;
}
};
予備知識: リンクされたリスト。
1. リンクリスト画像説明
想像してみてください。引き出しの中に必要なものが書かれた引き出しのアドレスが記載された小さなメモと、新しい引き出しを示すアドレスが記載された新しい小さなメモがあります。
2. リンクリストの C++ デモ
1. リンクリストの基本データ構造
struct ListNode
{
double value;
ListNode *next;
};
ListNode 構造体には、同じタイプのデータ構造体へのポインタが含まれる興味深いプロパティがあることがわかります
(1) 単一ノードに格納される値は、構造体または必要なデータ型になります。
(2)前のノードへのポインタを追加することもできます
struct data
{
int number;
string name;
string sex;
};
struct ListNode
{
struct data *info;
ListNode *next;
ListNode *last;
};
2. リンクリスト(単一リンクリスト)を作成します。
(1) ヘッドノード head を作成し、現在のノード p がヘッド ノードを指すようにします (p=head)
(2) 次のノード q を作成し、現在のノード p の次のノードが q になります (p->next= q)
(3) ノード p を 1 ビット後方に移動します (p = p->next)
#include <iostream>
#include<vector>
using namespace std;
struct ListNode{
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL){
}
};
int main()
{
int num;
cin >> num;
ListNode* head = new ListNode(num);
ListNode* p = head;
//利用尾插法创建一个链表
while (cin >> num){
ListNode* q = new ListNode(num);
p->next = q;
p = p->next;
}
//遍历这个链表,并输出每个结点的元素
ListNode* m = head;
while (m != nullptr){
cout << m->val << endl;
m = m->next;
}
return 0;
}
3. ノードの挿入
1. 元のリンク リストが空のリンク リストかどうかを判断します。そうである場合は、新しく追加されたノードをヘッドにポイントします。 2.
空のリンク リストでない場合は、リンク リストの最後に新しいノードを挿入します。
ListNode* insertNode(ListNode* head, int data){
ListNode* newNode = new ListNode(data);
ListNode* p = head;
if (p == nullptr){
head = newNode;
}
else{
while (p->next != nullptr){
p = p->next;
}
p->next = newNode;
}
return head;
}
4. ノードの削除
基本的な考え方: リンク リストに削除するノードがある場合、削除するノードの前のノードに移動し、ノードの次のポインタで削除するノードの次のノードを指します。
ListNode* deleteNode(ListNode* head, int data){
ListNode* p = head;
//首先判断是不是空链表
if (p == nullptr){
return head;
}
else{
//判断是不是删除头节点
if (p->val == data){
head = p->next;
delete p;
return head;
}
else{
//如果有该结点,遍历到待删除节点的前一节点
while (p->next != nullptr && p->next->val != data){
p = p->next;
}
//遍历完整个链表都没有待删除节点
if (p->next == nullptr){
return head;
}
else{
ListNode* deleteNode = p->next;
p->next = deleteNode->next;
delete deleteNode;
return head;
}
}
}
}
参考:
https://blog.csdn.net/slandarer/article/details/91863177