2つの順序付けられたリンクリストをマージする
アイデア:
この問題には多くの解決策があり、1つは再帰的で、もう1つは非再帰的です。特定の実装は難しくなく、コードを見るとはっきりとわかります。
コード:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if(l1==NULL) return l2;
if(l2==NULL) return l1;
ListNode* phead = NULL;
if(l1->val < l2->val){
phead = l1;
phead->next = mergeTwoLists(l1->next,l2);
}else{
phead = l2;
phead->next = mergeTwoLists(l1,l2->next);
}
return phead;
}
};
//非递归版本
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* phead= new ListNode(-1,NULL);
ListNode* op = phead;
while(l1!=NULL && l2!=NULL){
if(l1->val < l2->val){
op->next = l1;
l1=l1->next;
}else{
op->next = l2;
l2=l2->next;
}
op = op->next;
}
if(l1!=NULL) op->next = l1;
if(l2!=NULL) op->next = l2;
op = phead->next;
delete(phead);
return op;
}
};
逆リンクリスト
アイデア:この
質問は非常に単純です。コードを見るか、私が描いた絵を見てください。
コード:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head==NULL || head->next==NULL) return head;
ListNode *t,*p,*q;
t = NULL;
p = q = head;
while(q!=NULL){
q=q->next;
p->next = t;
t = p;
p = q;
}
return t;
}
};
リンクリストの下からk番目のノード
トピックリンク!
アイデア:この
質問は、高速ポインターと低速ポインター、または二重ポインターの質問です。1つは高速でもう1つは低速の、2つの変数は、高速ポインターを最初にkステップ移動させ、次に高速ポインターが最後に到達したときに同時に移動します。 。
コード:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* getKthFromEnd(ListNode* head, int k) {
if(head==NULL || k==0) return NULL;
ListNode *p,*q;
p = q = head;
for(int i=1;i<=k-1;++i){
q = q->next;
}
while(q->next!=NULL){
p=p->next;
q = q->next;
}
return p;
}
};
ループ検出
アイデア:この
質問は本当に一生懸命勉強する必要があります。最初に解決手順を捨ててください。
- 最初にそれが指輪かどうかを判断しますか?
- リングの長さxを見つけます。
- クイックポインタを最初にxステップ進みます。
- 次に、高速ポインタと低速ポインタが同時に移動し、それらが出会うノードがリングのエントリポイントになります。
(注:この質問は、上の図の2番目のケースのように、特別なケースも解決します。リンクリストの1つだけがリングです)
リングを判断する理由は誰もが理解しています。リングが形成されたときにのみ、その後の問題解決手順を実行できます。リングの長さが必要なのはなぜですか。実際、この理由を説明できる質問、つまり下からk番目のノードの質問があります。リングの長さは、高速ポインタを最初に非常に多くのステップに移動させることであり、また、速いポインタと遅いポインタはより速く出会う。高速ポインタを最初に移動させるため、高速ポインタがループを完了できるようにすると同時に、低速ポインタがループを歩く必要がないことを簡単に理解できます。
コード:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* check_huan(ListNode* head){
if(head==NULL) return NULL;
ListNode* slow = head;
ListNode* fast = slow->next;
while( fast!=NULL){
if(slow==fast) return slow; //这里也能处理特殊情况,比如只有一个节点的环
slow = slow->next;
fast = fast->next;
if(fast!=NULL) fast = fast->next;
}
return NULL;
}
ListNode *detectCycle(ListNode *head) {
ListNode* st = check_huan(head);
if(st==NULL) return NULL;
ListNode* t = st;
int num = 1;
while(st->next!=t){
st = st->next;
++num;
}
ListNode* fast = head;
for(int i=0;i<num;++i){
fast = fast->next;
}
while(fast!=head){
fast = fast->next;
head = head->next;
}
return fast;
}
};
Kフリップリスト
アイデア:この
質問には何かがあります。まず、リンクリストの反転に精通している必要があります。そうすれば、処理がはるかに簡単になります。まず、forループを使用してk長のサブリンクリストを読み取ります(注意してください)。 、特定のコード)を読み取れず、このサブリンクリストを関数に渡して処理すると、関数の値は、サブリンクリストを反転した後、ヘッドポインタとテールポインタを返します。このとき、スプライシングします。で十分であり、リンクリストのトラバースが完了するまで上記の手順が繰り返されます。
コード:
class Solution {
public:
// 翻转一个子链表,并且返回新的头与尾
pair<ListNode*, ListNode*> myReverse(ListNode* head, ListNode* tail) {
ListNode* prev = tail->next;
ListNode* p = head;
while (prev != tail) {
ListNode* nex = p->next;
p->next = prev;
prev = p;
p = nex;
}
return {
tail, head};
}
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode* hair = new ListNode(0);
hair->next = head;
ListNode* pre = hair;
while (head) {
ListNode* tail = pre;
// 查看剩余部分长度是否大于等于 k
for (int i = 0; i < k; ++i) {
tail = tail->next;
if (!tail) {
return hair->next;
}
}
ListNode* nex = tail->next;
pair<ListNode*, ListNode*> result = myReverse(head, tail);
head = result.first;
tail = result.second;
//tie(head, tail) = myReverse(head, tail);
pre->next = head;
tail->next = nex;
pre = tail;
head = tail->next;
}
return hair->next;
}
};