チェーン表シリーズの文章(二)
13597 ワード
前の文章はチェーンの基本的なデータ構造を実現しました.
まず、リンクノードのデータ構造を示します.
1.チェーンの最後からK番目のノードを削除する
例えば、与えられたチェーンテーブル:1->>2->>3->>4->5,n=5は、2->3->4->5方法の1つに戻ります.従来のやり方では、2回のスキャンで、最初のスキャンでチェーンの長さを得て、削除されるノードの順方向インデックスを求めて、第2回のスキャンでノードを削除します.
時間複雑度O(n)、空間複雑度O(1)
時間複雑度O(n)、空間複雑度O(1)
2. ランダムポインタ付きのチェーンテーブルをコピーします.ランダムポインタは、チェーンテーブルのノードを指しますか?それとも空ですか?
インデックスに対応するノードが得られ、そのノードに対してランドマークポインタが向けられます.
時間複雑度O(n 2)、空間複雑度O(n)
方法2:チェーンテーブルをコピーしたノードをソースチェーンの対応ノードに1つずつ挿入した後、
ソースチェーン(nextポインタのみ表示):s 1->s2->s3->s 4
挿入後:s 1->>d 1->>s 2->s 3->d 3->s 4->d 4をコピーします.例えば、d 1のランドムポインタをコピーするには、d 1->ランドm=s 1->ランドm->nextだけでいいです.
時間複雑度O(n)、空間複雑度O(n)
3.チェーン時計に環があるかどうかを判断し、もしあれば、交点を見つけます.
判断にリングがある:
方法1:hashは、hashテーブルでノードごとのアドレスを記録し、最初にhash値が存在するとき、交差を示し、同時に最初のノードを見つけました.そうでなければ、空に行くと交点がありません.
時間複雑度O(n)、空間複雑度O(n)
方法2:減速の針、fastの針は毎回2歩を歩いて、slowの針は毎回1歩を歩いて、だからfastの針はslow針に対して毎回1つ歩いて、もし環があるならば、きっと有限な歩で交差して、交点を判断しますと、博文を参考にします:
http://www.cnblogs.com/carlsama/p/4127201.html
私のレベルが限られていますので、文章の中には避けられないところがあります.
まず、リンクノードのデータ構造を示します.
1 struct ListNode {
2 int var;
3 ListNode *next;
4 ListNode(int v = 0 ) : var(v), next(NULL) { }
5 };
1.チェーンの最後からK番目のノードを削除する
例えば、与えられたチェーンテーブル:1->>2->>3->>4->5,n=5は、2->3->4->5方法の1つに戻ります.従来のやり方では、2回のスキャンで、最初のスキャンでチェーンの長さを得て、削除されるノードの順方向インデックスを求めて、第2回のスキャンでノードを削除します.
時間複雑度O(n)、空間複雑度O(1)
1 ListNode *removeNthNodeFromEndOfList(ListNode *head, int k) {
2 if( !head || k < 1 ) return NULL;
3 int len = 0;
4 ListNode *p = head, newhead(-1);
5 newhead.next = p;
6 for( ; p; p = p->next ) len++;// ,
7 k = len - k;//
8 if(k < 0) return NULL;
9 p = &newhead;
10 while( k-- ) p = p->next;// ,
11
12 ListNode *tmp = p->next;
13 p->next = tmp->next;
14 delete tmp;
15 return newhead.next;
16 }
方法2:2つのポインタ、1番目のポインタは先にK歩、そして2つのポインタは同時に進み、2番目のポインタがリンクの最後に来たとき、最初のポインタが指すノードは削除されるノードです.時間複雑度O(n)、空間複雑度O(1)
1 ListNode *removeNthNodeFromEndOfList(ListNode *head, int k) {
2 if(!head || k < 1) return NULL;
3 ListNode newhead(-1), *p = &newhead, *q = &newhead;
4 newhead.next = head;
5 while( k-- && q ) q = q->next; //q->next k
6 if( !q ) return NULL;
7 while( p && q->next ) { p = p->next; q = q->next; }//p->next
8 q = p->next;
9 p->next = q->next;
10 delete q;
11 return newhead.next;
12 }
2. ランダムポインタ付きのチェーンテーブルをコピーします.ランダムポインタは、チェーンテーブルのノードを指しますか?それとも空ですか?
1 struct RandomListNode {
2 int var;
3 RandomListNode *next, *random;
4 RandomListNode(int v) : var(v), next(NULL), random(NULL) { }
5 };
方法1:従来のやり方で、まずチェーンをスキャンしてnextポインタをコピーする.その後、各ノードに対して、ランダムノードのチェーンテーブル内のインデックスを特定し、各randomノードをコピーする際に、nextポインタをスキャンする.インデックスに対応するノードが得られ、そのノードに対してランドマークポインタが向けられます.
時間複雑度O(n 2)、空間複雑度O(n)
1 RandomListNode *copyRandomList(RandomListNode *head) {
2 if( !head ) return NULL;
3 int n = 0;
4 RandomListNode *p = head, newhead(-1), r = &newhead;
5 for( ; p; p = p->next ) {// , next ,
6 r->next = new RandomListNode(p->var);
7 r = r->next; n++;
8 }
9 r = &newhead;
10 for(p = head; p; p = p->next) {// random
11 if(NULL == p->random)
12 r->next->random = NULL;
13 else if(p->random == p)
14 r->next->random = r->next;
15 else {//
16 int k = n;
17 RandomListNode *q = p->random;
18 RandomListNode *h = newhead.next;
19 while(q) {k--; q = q->next;}//random
20 while(k--) {h = h->next;}//
21 r->next->random = h;
22 }
23 r = r->next;
24 }
25 return newhead.next;
26 }
方法2:チェーンテーブルをコピーしたノードをソースチェーンの対応ノードに1つずつ挿入した後、
ソースチェーン(nextポインタのみ表示):s 1->s2->s3->s 4
挿入後:s 1->>d 1->>s 2->s 3->d 3->s 4->d 4をコピーします.例えば、d 1のランドムポインタをコピーするには、d 1->ランドm=s 1->ランドm->nextだけでいいです.
時間複雑度O(n)、空間複雑度O(n)
1 RandomList *copyRandomList(RandomListNode *head) {
2 if( !head ) return NULL;
3 RandomListNode newhead(-1);
4 for( RandomListNode* p = head; p != NULL ) { //
5 RandomListNode* q = new RandomListNode(p->var);
6 q->next = p->next;
7 p->next = q;
8 p = q->next;
9 }
10 for( RandomListNode* p = head; p != NULL ) {// random
11 if (p->random != NULL)
12 p->next->random = p->random->next;
13 p = p->next->next;
14 }
15 for( RandomListNode* p = head, *d_p = &newhead; p != NULL ) {//
16 d_p->next = p->next;
17 d_p = d_p->next;
18 p->next = p->next->next;
19 p = p->next;
20 }
21 return newhead.next;
22 }
3.チェーン時計に環があるかどうかを判断し、もしあれば、交点を見つけます.
判断にリングがある:
方法1:hashは、hashテーブルでノードごとのアドレスを記録し、最初にhash値が存在するとき、交差を示し、同時に最初のノードを見つけました.そうでなければ、空に行くと交点がありません.
時間複雑度O(n)、空間複雑度O(n)
方法2:減速の針、fastの針は毎回2歩を歩いて、slowの針は毎回1歩を歩いて、だからfastの針はslow針に対して毎回1つ歩いて、もし環があるならば、きっと有限な歩で交差して、交点を判断しますと、博文を参考にします:
http://www.cnblogs.com/carlsama/p/4127201.html
私のレベルが限られていますので、文章の中には避けられないところがあります.