๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
์ฝ”๋”ฉํ…Œ์ŠคํŠธ/์•Œ๊ณ ๋ฆฌ์ฆ˜&์ž๋ฃŒ๊ตฌ์กฐ

3. Linked List

by moon101 2024. 3. 9.

๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ๋ž€?

ํฌ์ธํ„ฐ๋กœ ์—ฐ๊ฒฐ๋œ ๋…ธ๋“œ๋“ค์˜ ์ปฌ๋ ‰์…˜์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๊ณ , ์Šคํƒ, ํ, ํ•ด์‹œ ํ…Œ์ด๋ธ”์„ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋‹ค. ์‹œ์ž‘ ์ง€์ ์— ๋…ธ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์‚ญ์ œํ•˜๋Š” ๊ฒƒ์€ O(1) ์ƒ์ˆ˜ ์‹œ๊ฐ„์ด ์†Œ์š”๋œ๋‹ค. 

 

๋…ธ๋“œ ํด๋ž˜์Šค ์ฝ”๋“œ ์˜ˆ์‹œ

public class Node {
    int val;
    Node next;
    ListNode() {}
    Node(int val) {
        this.val = val;
    }
    Node(int val, Node next) {
    	this.val = val;
        this.next = next;
    }
}

 

์ฝ”๋”ฉํ…Œ์ŠคํŠธ ํŒ ๐Ÿ—๏ธ

Recursion๋„ ์•Œ์•„์•ผ ํ•˜๊ณ  ๊ทธ ์–ด๋ ต๋‹ค๋Š” ํฌ์ธํ„ฐ๋ฅผ ํ™œ์šฉํ•ด์„œ ๋ฌธ์ œ๋ฅผ ํ’€์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋ฆผ์„ ๋งŽ์ด ๊ทธ๋ ค๋ณด๋ฉด์„œ ์ฝ”๋“œ๋ฅผ ๋”ฐ๋ผ๊ฐ€ ๋ณด๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค. ๋งŒ์•ฝ Easy ๋ฌธ์ œ๋„ ๋„ˆ๋ฌด ์–ด๋ ต๊ฒŒ ๋Š๊ปด์ง„๋‹ค๋ฉด ์žฌ๊ท€๋‚˜ ๋‹ค๋ฅธ ๋ฌธ์ œ๋“ค์„ ํ’€๋ฉด์„œ ์‹œ๊ฐ„์ด ์ข€ ์ง€๋‚œ ๋‹ค์Œ์— ๋ณด๋ฉด ์ดํ•ด๊ฐ€ ๋” ์ž˜ ๋  ์ˆ˜๋„ ์žˆ์œผ๋‹ˆ ๋ง‰ํžˆ๋ฉด ์ž ๊น ์‰ฌ์—ˆ๋‹ค ๊ฐ€๋Š” ๊ฒƒ๋„ ์ข‹์€ ๋ฐฉ๋ฒ•์ด๋‹ค. 

Runner Technique 
๐ŸŽƒ ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ ๋ฌธ์ œ์—์„œ ๋งŽ์ด ํ™œ์šฉ
๐ŸŽƒ slow and fast pointer

Recursion
๐ŸŽƒ ์žฌ๊ท€๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ, Space Complexity๋Š” O(n) ์ธ๋ฐ
๐ŸŽƒ ์—ฌ๊ธฐ์„œ n์€ ์žฌ๊ท€์˜ ๊นŠ์ด๋ฅผ ๋œปํ•œ๋‹ค

 

์ฝ”๋“œ

๐Ÿ’ง slow/fast ํฌ์ธํ„ฐ ์‚ฌ์šฉ ์‹œ while๋ฌธ ์กฐ๊ฑด ์ž‘์„ฑ๋ฒ•

slow, fast ํฌ์ธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฌธ์ œ๋ฅผ ํ‘ธ๋Š” ๊ฒฝ์šฐ, ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฆฌํŠธ์ฝ”๋“œ 141๋ฒˆ ๋ฌธ์ œ Linked List Cycle์€ slow ํฌ์ธํ„ฐ๋ฅผ ํ•œ์นธ์”ฉ, fast ํฌ์ธํ„ฐ๋ฅผ ๋‘์นธ์”ฉ ์˜ฎ๊ธฐ๋‹ค๊ฐ€ ๋‘˜์ด ๋งŒ๋‚˜๋ฉด ํ•ด๋‹น ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ์— ์‹ธ์ดํด์ด ์žˆ๋‹ค๊ณ  ์•Œ ์ˆ˜ ์žˆ๋Š”๋ฐ ์ด๋•Œ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. 

๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ์— ์‹ธ์ดํด์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ์ฝ”๋“œ

์—ฌ๊ธฐ์„œ while๋ฌธ์— fast๊ฐ€ null์ด ์•„๋‹๋•Œ ๊ทธ๋ฆฌ๊ณ  fast.next๊ฐ€ null์ด ์•„๋‹๋•Œ๋ฅผ break ์กฐ๊ฑด์œผ๋กœ ์ž‘์„ฑํ•ด ์ค˜์•ผํ•œ๋‹ค. ์™œ๋ƒ๋ฉด ์‹ธ์ดํด์ด ์—†๋Š” linearํ•œ ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ์ผ ๊ฒฝ์šฐ์—๋Š” while loop์„ ๋น ์ ธ๋‚˜์™€์•ผ ํ•˜๋Š”๋ฐ ์ด๋•Œ ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ์˜ ๋…ธ๋“œ์˜ ๊ฐฏ์ˆ˜๊ฐ€ ํ™€์ˆ˜์ผ๋•Œ์™€ ์ง์ˆ˜์ผ๋•Œ๋ฅผ ๊ณ ๋ คํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. 

ํ•œ์นธ์”ฉ ์›€์ง์ด๋Š” slow๋ณด๋‹ค fast๊ฐ€ ํ•ญ์ƒ ๋” ์•ž์— ๊ฐ€๊ธฐ ๋•Œ๋ฌธ์— fast ํฌ์ธํ„ฐ๋ฅผ ํ™•์ธํ•ด์•ผ ํ•˜๊ณ  ๊ทธ๋ฆผ์—์„œ์™€ ๊ฐ™์ด ์ง์ˆ˜์ผ ๊ฒฝ์šฐ๋Š” fast ํฌ์ธํ„ฐ๊ฐ€ null์ด ๋˜์ง€๋งŒ ํ™€์ˆ˜์ผ ๊ฒฝ์šฐ์—๋Š” fast.next๊ฐ€ null์ธ์ง€๋ฅผ ํ™•์ธํ•ด์•ผ NullPointerException ์—๋Ÿฌ ์—†์ด ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆœํšŒํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

๐Ÿ’ง Reverse Linked List 

Linked list๋ฅผ reverseํ•˜๋ ค๋ฉด ๊ฒฐ๊ตญ ๊ธฐ์กด ๋…ธ๋“œ์˜ next๊ฐ€ ๋‹ค์Œ ๋…ธ๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ ์ด์ „ ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฅดํ‚ค๋„๋ก ๋ฐ”๊ฟ”์ค˜์•ผ ํ•˜๊ณ  recursive, iterative ๋ฐฉ๋ฒ• ๋‘๊ฐ€์ง€๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

Recursive ๋ฐฉ๋ฒ•

1. base case: ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ๊ฐ€ empty๊ฑฐ๋‚˜ ํ•œ๊ฐœ์˜ ๋…ธ๋“œ๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด ์ด๋ฏธ reversed ๋œ ์ƒํƒœ์ž„์œผ๋กœ head๋ฅผ ๋ฆฌํ„ด

2. base case๊ฐ€ ์•„๋‹ˆ๋ฉด ์žฌ๊ท€์ ์œผ๋กœ reverse linked list ํ•จ์ˆ˜ ํ˜ธ์ถœ (reverseList(head.next))

3. ์ƒˆ๋กœ์šด ํ—ค๋“œ์— ๋Œ€ํ•œ ์ฐธ์กฐ ์ €์žฅ (ListNode newHead = reverseList(head.next))

4. reverse linked list (head.next.next = head)

5. ์ˆœํ™˜์ฐธ์กฐ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ ํฌ์ธํ„ฐ์˜ ์—ฐ๊ฒฐ์„ ๋„๋กœ ๋Š์–ด์คŒ (head.next = null)

6. ์ƒˆ๋กœ์šด ํ—ค๋“œ ๋ฆฌํ„ด (return newHead)

reverse linked list recursive way

 

 

reverse linked listํ•˜๋Š” ๋ถ€๋ถ„์ธ head.next.next = head๊ฐ€ ์ดํ•ด๊ฐ€ ์ž˜ ์•ˆ๋˜๋ฉด, head.next๋ฅผ ์ค‘๊ฐ„์— ํ•œ๋ฒˆ front ๋ณ€์ˆ˜๋กœ ์ €์žฅํ•˜๊ณ  front์˜ ๋‹ค์Œ์ด head๋ฅผ ๊ฐ€๋ฅดํ‚ฌ ์ˆ˜ ์žˆ๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜๋„ ์žˆ๋‹ค.  

head.next์˜ next ํฌ์ธํ„ฐ๊ฐ€ head๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋„๋ก ๋ฐ”๊ฟ”์ค˜์•ผ reverse ํ•  ์ˆ˜ ์žˆ๋‹ค

 

 

Iterative ๋ฐฉ๋ฒ•

1. temp ํฌ์ธํ„ฐ๋ฅผ ์„ ์–ธํ•œ ๋’ค head์— ์œ„์น˜ํ•ด์„œ ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆœํšŒํ•˜๋Š”๋ฐ ์‚ฌ์šฉ

2. prev ํฌ์ธํ„ฐ๋ฅผ null๋กœ ์ƒ์„ฑํ•œ ๋‹ค์Œ ์ด์ „ ๋…ธ๋“œ๋ฅผ ํŠธ๋ž™ํ•˜๋Š”๋ฐ ํ™œ์šฉ. next ํฌ์ธ์˜ ๋ฐฉํ–ฅ์„ ๋ฐ”๊พธ๋Š”๋ฐ ์‚ฌ์šฉ

3. temp ํฌ์ธํ„ฐ๋ฅผ ์ด๋™ํ•˜๋ฉด์„œ ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ ์ „์ฒด๋ฅผ ์ˆœํšŒ. temp ํฌ์ธํ„ฐ๊ฐ€ null์ผ ๊ฒฝ์šฐ ์ˆœํšŒ ์ข…๋ฃŒ

4. temp ํฌ์ธํ„ฐ๊ฐ€ ๋‹ค์Œ์œผ๋กœ ์ด๋™ํ•  ๋…ธ๋“œ์˜ ์ฐธ์กฐ๋ฅผ ์žƒ์ง€ ์•Š๊ธฐ ์œ„ํ•ด temp.next๋ฅผ ์ˆ˜์ •ํ•˜๊ธฐ ์ „์— front ํฌ์ธํ„ฐ์— ์ €์žฅ

5. temp ํฌ์ธํ„ฐ๊ฐ€ prev๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ์ˆ˜์ •

----- next iteration์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด prev, temp ์œ„์น˜๋ฅผ ํ•œ์นธ์”ฉ ์ด๋™ ----

6. prev๋ฅผ ํ˜„์žฌ ๋…ธ๋“œ๋กœ ์ด๋™

7. temp ํฌ์ธํ„ฐ๋ฅผ front ํฌ์ธํ„ฐ๋กœ ์ด๋™

8. temp๊ฐ€ ๋„์ด ๋˜๋ฉด reversed linked list์˜ ์ƒˆ๋กœ์šด head์ธ prev ํฌ์ธํ„ฐ ๋ฆฌํ„ด

reverse linked list iterative way

 

๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ ๋ฌธ์ œ

LeetCode

206. Reverse Linked List (iterativeํ•˜๊ณ  recursive ๋ฐฉ๋ฒ• ๋‘๊ฐ€์ง€๋กœ ํ’€์–ด๋ด์•ผํ•จ)

876. Middle of the Linked List (fast and slow pointer ํ™œ์šฉ. Tortoise and Hare ์•Œ๊ณ ๋ฆฌ์ฆ˜)

21.Merge Two Sorted Lists (์ด๊ฒƒ๋„ iterative/recursive ๋ฐฉ๋ฒ• ๋‘๊ฐ€์ง€๋กœ ํ’€์–ด๋ด์•ผ ํ•˜๊ณ  ์ด๋ฏธ ์ •๋ ฌ์ด ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํˆฌํฌ์ธํ„ฐ ๊ฐœ๋…์„ ํ™œ์šฉํ•ด์„œ ๋จธ์ง€ํ•˜๋ฉด ๋  ๊ฒƒ ๊ฐ™์ง€๋งŒ next pointer๋ฅผ ๋ณ€๊ฒฝํ•ด์ค˜์•ผ ํ•ด์„œ Easy ๋ฌธ์ œ์ด์ง€๋งŒ ์ƒ๊ฐ๋ณด๋‹ค ์–ด๋ ค์›€ โ˜…โ˜…โ˜…)

19. Remove Nth Node From End of List (fast/slow pointer ํ™œ์šฉ. fast ํฌ์ธํ„ฐ๋ฅผ n ๋…ธ๋“œ ์•ž์— ์œ„์น˜ํ•œ ๋‹ค์Œ slow/fast ํฌ์ธํ„ฐ๋ฅผ 1์”ฉ ์›€์ง์ด๋ฉด, fast ํฌ์ธํ„ฐ๊ฐ€ ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ์— ์žˆ์„ ๋•Œ slow ํฌ์ธํ„ฐ๋Š” ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ์—์„œ nth๋…ธ๋“œ ์•ž์— ์œ„์น˜)

2. Add Two Numbers (๋งŒ์•ฝ์— ์ƒˆ๋กœ์šด ๋…ธ๋“œ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค๋ฉด dummy node ํ™œ์šฉํ•˜๋ฉด ์ฝ”๋“œ๊ฐ€ ๊น”๋”ํ•ด์ง. int carry ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•ด์„œ 10 ์ •๋ณด ์ €์žฅ)

237. Delete Node in a Linked List (๋ฌธ์ œ ์„ค๋ช…์ด ๋ช…ํ™•ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋Š”๋ฐ ๋ฆฌํŠธ์ฝ”๋“œ ๋””์Šค์ปค์…˜์— Best๋กœ ์ •๋ ฌํ–ˆ์„ ๋•Œ ๋‚˜์˜ค๋Š” ๋งจ ์ฒ˜์Œ ๊ธ€์„ ์ฐธ๊ณ ํ•˜๋ฉด ์ธ์‚ฌ์ดํŠธ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Œ. "no one can delete the node correctly without access to its predecessor")

160. Intersection of Two Linked Lists (๋ฆฌ์ŠคํŠธ์˜ ๊ธธ์ด๋ฅผ ๊ตฌํ•ด์„œ ํ’€ ์ˆ˜๋„ ์žˆ์ง€๋งŒ ๋‘๊ฐœ์˜ ๋”๋ฏธ ๋…ธ๋“œ๋ฅผ ํ—ค๋“œ์— ์œ„์น˜ํ•œ ๋‹ค์Œ ๋ฆฌ์ŠคํŠธ ์ˆœํšŒ. null์ผ ๋•Œ ํ•ด๋‹น ๋…ธ๋“œ๋ฅผ ๋ฐ˜๋Œ€ ๋ฆฌ์ŠคํŠธ์˜ ํ—ค๋“œ์— ์œ„์น˜ํ•œ ๋‹ค์Œ ๋‘๊ฐœ์˜ ๋”๋ฏธ ๋…ธ๋“œ๊ฐ€ ๋งŒ๋‚  ๋•Œ๊นŒ์ง€ ์ˆœํšŒ)

141. Linked List Cycle (slow/fast ํฌ์ธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ๋ฌธ์ œ)

25. Reverse Nodes in k-Group (๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ๋ฅผ reverse ํ•˜๋Š” ๋ฐฉ๋ฒ•, ์žฌ๊ท€๋ฅผ ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ’€ ์ˆ˜ ์žˆ์Œ โ˜…โ˜…โ˜…โ˜…)

234. Palindrome Linked List (์ค‘๊ฐ„ ๋…ธ๋“œ๋ฅผ ์ฐพ์•„์„œ ๋‘๋ฒˆ์งธ ๋ถ€๋ถ„์„ reverse. ํฌ์ธํ„ฐ์˜ ์œ„์น˜๊ฐ€ ํ—ท๊ฐˆ๋ฆด ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๊ทธ๋ฆผ์œผ๋กœ ๊ทธ๋ ค๋ด์•ผํ•จ)

142. Linked List Cycle 2 (141๋ฒˆ์˜ ์‹ฌํ™” ๋ฒ„์ „. ์šฐ์„  cycle์ด ์žˆ๋Š”์ง€ ์ฐพ๊ณ , slowํฌ์ธํ„ฐ๋Š” starting point์—, fast ํฌ์ธํ„ฐ๋Š” collision point์— ์œ„์น˜ํ•œ ๋’ค ํ•œ๊ฐœ์”ฉ ์ด๋™ํ•˜๋‹ค๊ฐ€ ๋‘˜์ด ๋งŒ๋‚˜๋Š” ๊ณณ์ด starting ํฌ์ธํŠธ์ธ๋ฐ ์ด๊ฒƒ์— ๋Œ€ํ•œ ์„ค๋ช…์€ takeUForward ๋™์˜์ƒ์— ์ž˜ ๋‚˜์™€์žˆ์Œ)

61. Rotate List (๋ฐฐ์—ด๋ฌธ์ œ์—์„œ๋„ ๊ทธ๋ ‡์ง€๋งŒ k๋ฒˆ์„ rotateํ•˜๋ผ๋Š” ๋ฌธ์ œ๊ฐ€ ๋‚˜์˜ค๋ฉด % modulo๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•จ. ์ด ๋ฌธ์ œ์—์„œ๋Š” recursion๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋ƒฅ k๋ฒˆ ํšŒ์ „ํ•˜๋ฉด StackOverflowError๊ฐ€ ๋œธ)

138. Copy List with Random Pointer (deep copyํ•ด์•ผํ•จ. ํ•ด์‹œ๋งต์„ ์‚ฌ์šฉํ•ด์„œ ํ’€์–ด๋„ ๋˜๋Š”๋ฐ  Space Complexity๋ฅผ O(1)๋กœ ์ค„์ด๋ ค๋ฉด ์ƒˆ๋กœ ๋งŒ๋“  ๋…ธ๋“œ๋ฅผ ๊ธฐ์กด ๋…ธ๋“œ ๋ฆฌ์ŠคํŠธ ์ˆœ์„œ ์‚ฌ์ด์‚ฌ์ด์— ์œ„์น˜ํ•ด์„œ ํ’€ ์ˆ˜ ์žˆ์Œ)

1171. Remove Zero Sum Consecutive Nodes from Linked List (prefix sum๊ณผ hashmap ์‚ฌ์šฉ)

 

 

์ฐธ๊ณ ์ž๋ฃŒ

๋„์„œ: ์ฝ”๋”ฉ ์ธํ„ฐ๋ทฐ ์™„์ „๋ถ„์„

https://takeuforward.org/data-structure/reverse-a-linked-list/

https://arminnorouzi.github.io/posts/2023/06/blog-post-3/

https://www.youtube.com/watch?v=2T-A_GFuoTo&t=650s

https://github.com/jwasham/coding-interview-university?tab=readme-ov-file#linked-lists

 

 

 
 
 
 
 
 

'์ฝ”๋”ฉํ…Œ์ŠคํŠธ > ์•Œ๊ณ ๋ฆฌ์ฆ˜&์ž๋ฃŒ๊ตฌ์กฐ' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

2. Arrays  (0) 2024.03.02

๋Œ“๊ธ€