File tree Expand file tree Collapse file tree 3 files changed +106
-2
lines changed Expand file tree Collapse file tree 3 files changed +106
-2
lines changed Original file line number Diff line number Diff line change @@ -16,7 +16,7 @@ class LinkedList {
1616 * @param dataOrNode
1717 * @returns {Node }
1818 */
19- addLast ( dataOrNode ) {
19+ addLast ( dataOrNode , once = false ) {
2020 let node = getNode ( dataOrNode ) ;
2121 if ( this . head ) {
2222 this . tail . next = node ;
@@ -27,7 +27,7 @@ class LinkedList {
2727 while ( node ) {
2828 this . tail = node ;
2929 this . length ++ ;
30- if ( ! node . next ) { break ; }
30+ if ( ! node . next || once ) { break ; }
3131 node = node . next ;
3232 }
3333 return node ;
Original file line number Diff line number Diff line change 1+ const LinkedList = require ( './linkedlist' ) ;
2+
3+
4+ LinkedList . prototype . getLoop = loopDetection ;
5+
6+ /**
7+ * O(n) / O(1) -
8+ * @returns {* }
9+ */
10+ function loopDetection ( ) {
11+ let slow = this . head ;
12+ let fast = this . head ;
13+
14+ // first collision will happen k nodes before the beginning of the loop.
15+ // k it also happen to be the distance from the head to the beginning of the loop
16+ while ( slow && fast . next ) {
17+ slow = slow . next ;
18+ fast = fast . next . next ;
19+ if ( slow === fast ) { break ; }
20+ }
21+
22+ // loop detected
23+ // rewind slow and move both one at time.
24+ // When they meet together is the beginning of the loop
25+ if ( slow === fast ) {
26+ for ( slow = this . head ; slow && fast ; slow = slow . next , fast = fast . next ) {
27+ if ( slow === fast ) {
28+ return slow ;
29+ }
30+ }
31+ }
32+
33+ // no loop detected
34+ return false ;
35+
36+ }
37+
38+ /**
39+ * O(n) / O(n) - hashmap of addresses
40+ * @returns {* }
41+ */
42+ function hasLoop ( ) {
43+ var map = new Map ( ) ;
44+
45+ for ( let i = this . head ; i ; i = i . next ) {
46+ if ( map . has ( i ) ) {
47+ return i ;
48+ } else {
49+ map . set ( i , 1 ) ;
50+ }
51+ }
52+
53+ return false ;
54+ }
55+
56+ module . exports = LinkedList ;
Original file line number Diff line number Diff line change 1+ const expect = require ( 'chai' ) . expect ;
2+ const LinkedList = require ( './loop-detection' ) ;
3+
4+ describe ( 'LinkedList: loop detection' , function ( ) {
5+ let list ;
6+
7+ beforeEach ( function ( ) {
8+ list = new LinkedList ( ) ;
9+ } ) ;
10+
11+ it ( 'should return false when no loops are detected' , function ( ) {
12+ list . addLast ( 'a' ) ;
13+ list . addLast ( 'b' ) ;
14+ list . addLast ( 'c' ) ;
15+ list . addLast ( 'd' ) ;
16+ list . addLast ( 'e' ) ;
17+
18+ expect ( list . getLoop ( ) ) . to . equal ( false ) ;
19+ } ) ;
20+
21+ it ( 'should detect loop: case 1' , function ( ) {
22+ list . addLast ( 'a' ) ;
23+ const b = list . addLast ( 'b' ) ;
24+ list . addLast ( b , true ) ;
25+
26+ expect ( list . getLoop ( ) ) . to . equal ( b ) ;
27+ } ) ;
28+
29+ it ( 'should detect loop: case 2' , function ( ) {
30+ const a = list . addLast ( 'a' ) ;
31+ list . addLast ( 'b' ) ;
32+ list . addLast ( 'c' ) ;
33+ list . addLast ( a , true ) ;
34+
35+ expect ( list . getLoop ( ) ) . to . equal ( a ) ;
36+ } ) ;
37+
38+ it ( 'should detect loop: case 3' , function ( ) {
39+ list . addLast ( 'a' ) ;
40+ list . addLast ( 'b' ) ;
41+ const c = list . addLast ( 'c' ) ;
42+ list . addLast ( 'd' ) ;
43+ list . addLast ( 'e' ) ;
44+ list . addLast ( c , true ) ;
45+
46+ expect ( list . getLoop ( ) ) . to . equal ( c ) ;
47+ } ) ;
48+ } ) ;
You can’t perform that action at this time.
0 commit comments