目次
1. トピックの説明
2.思考分析
全体的な考え方: 2 つのリンク リストを作成し、 x 未満のノードとx 以上のノードをそれぞれ保存し、それぞれ末尾の挿入を実行します。
次の理由により、この質問には番兵の位置を使用する方が簡単です(多くの空の状況を回避できます)。
(1) センチネル ビットを使用すると、末尾が挿入されたときに 2 つのリンク リストが空であるという状況を考慮する必要がありません。
(2) 2 つの連結リストを連結するときに空かどうかを考慮する必要がありません。
(3) たとえ片方のリンクリストが空であっても、センチネル位置の先頭ノードは存在するので、通常のリンクで十分である。
構造体ポインターlheadおよびltailを使用して値が x 未満のリンク リストを表し、構造体ポインターgheadおよびgtailを使用して値が x 以上のリンク リストを表します。
malloc() 関数を使用して 2 つのノード、つまり 2 つのリンクされたリストのセンチネル位置を適用し、lhead と ltail が先頭で一方を指し、ghead と gtail が先頭でもう一方を指すようにします。
次に、元のリンク リストをトラバースするための構造体ポインタ cur を作成します。cur が空でない場合は、while ループを使用してノードをトラバースします。
ノードの値が x より小さい場合、このノードを最初のリンク リストに末尾挿入します ( ltail->next=cur )。次に、 ltai を 1 ステップ後退させます ( ltai=ltail->next )。
ノードの値が x 以上の場合、ノードの末尾を 2 番目のリンク リストに挿入します ( gtail->next=cur )。次に、 gtail を 1 ステップ後退させます ( gtail=gtail->next )。
ノードを挿入した後、 cur を一歩戻します( cur=cur->next )。cur が空の場合はループを停止します。
次に、2 つのリンクされたリストをリンクします。( ltail->next=ghead->next )。
非常に注意が必要なことが 1 つあります。!!
gtail->next=NULL を設定します
そうしないとリングが現れる可能性があります。
lhead はセンチネルの位置を指しているため、lhead を 1 つ後ろに移動する必要があります( lhead=lhead->next )。
lhead の次の位置が見つからない可能性があるため、lhead の次の位置を保存する構造体ポインタ headを導入します。( struct ListNode *head=lhead->next )。
次に、メモリ リークを防ぐために、free() を使用して 2 つのセンチネル ビット(つまり、free(lhed)とfree(ghead) ) を解放する必要があります。
最後に、頭に戻ります。
3. コードの実装
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class Partition {
public:
ListNode* partition(ListNode* pHead, int x) {
struct ListNode *lhead,*ltail,*ghead,*gtail;
lhead=ltail=(struct ListNode*)malloc(sizeof(struct ListNode));
ghead=gtail=(struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode *cur=pHead;
while(cur)
{
if(cur->val<x)
{
ltail->next=cur;
ltail=ltail->next;
}
else
{
gtail->next=cur;
gtail=gtail->next;
}
cur=cur->next;
}
ltail->next=ghead->next;
//不空,可能导致出现环
gtail->next=NULL;
struct ListNode *head=lhead->next;
free(lhead);
free(ghead);
return head;
}
};