Use “pseudo head node” 虛擬頭節點
When delete node from linked list, we need to be at “previous” node, then can delete NEXT node
cur
node, than can
cur.next
node# python
# https://youtu.be/Y4oQJklHxVo?t=965
next = cur.next.next cur.
# python
# Definition for singly-linked list.
class ListNode(object):
def __init__(self, val=0, next=None):
self.val = val
self.next = next
// java
// Single Linkedlist
public class ListNode{
// attr
public int val;
public ListNode next;
// constructor
public ListNode(){
}
public ListNode(int val){
this.val = val;
}
ListNode(int val, ListNode next){
this.val = val;
this.next = next;
}
}
// init a ListNode
= new ListNode(1);
ListNode node1 = new ListNode(2);
ListNode node2 = new ListNode(3);
ListNode node3
// motify node's value
.val = 0;
node1
// connect nodes
.next = node2;
node1.next = node3; node2
// java
// Double linked list
// LC 146
public class Node {
int key;
int val;
Node prev;
Node next;
public Node(int key, int val) {
this.key = key;
this.val = val;
this.prev = null;
this.next = null;
}
}
= dict()
dic = n = head
m = Node(m.val) dic[m]
self.children = defaultdict(Node)
// java
// single Linklist
public class ListNode {
int val;
;
ListNode nextListNode(int x) { val = x; }
}
# python
class Node:
"""
# constructor
# A single node of a singly linked list
"""
def __init__(self, data=None, next=None):
self.data = data
self.next = next
class LinkedList:
"""
# A Linked List class with a single head node
"""
def __init__(self):
self.head = Node()
def get_length(self):
"""
# get list length method for the linked list
i.e.
before : 1 -> 2 -> 3
after : 3
"""
= self.head
current = 0
length while current:
= current.next
current += 1
length return length
def get_tail(self):
"""
# get list tail method for the linked list
i.e.
before : a -> b -> c
after : c
"""
= self.head
current while current:
= current.next
current return current
def print(self):
"""
# print method for the linked list
i.e.
before : 1 -> 2 -> 3
after : 1 2 3
"""
= self.head
current while current:
print (current.data)
= current.next
current
def append(self, data):
"""
# append method that append a new item at the end of the linkedlist
i.e.
before : 1 -> 2 -> 3
after : 1 -> 2 -> 3 -> 4
"""
= Node(data)
newNode if self.head:
= self.head
current while current.next:
= current.next
current next = newNode
current.else:
self.head = newNode
def prepend(self, data):
"""
# append method that append a new item at the head of the linkedlist
i.e.
before : 1 -> 2 -> 3
after : 0 -> 1 -> 2 -> 3
"""
= Node(data)
newNode if self.head:
= self.head
current self.head = newNode
next = current
newNode.= current.next
current else:
self.head = newNode
def insert(self, idx, data):
"""
# append method that append a new item within the linkedlist
i.e.
before : 1 -> 2 -> 3
insert(1, 2.5)
after : 1 -> 2 -> 2.5 -> 3
before : 1 -> 2 -> 3
insert(0, 0)
after : 0 -> 1 -> 2 -> 3
before : 1 -> 2 -> 3
insert(2, 4)
after : 1 -> 2 -> 3 -> 4
"""
= self.head
current = self.get_length()
ll_length
if idx < 0 or idx > self.get_length():
print ("idx out of linkedlist range, idx : {}".format(idx))
return
elif idx == 0:
self.prepend(data)
elif idx == ll_length:
self.append(data)
else:
= Node(data)
newNode = self.head
current = 0
cur_idx while cur_idx < idx-1:
= current.next
current += 1
cur_idx next = current.next
newNode.next = newNode
current.
def remove(self, idx):
"""
# remove method for the linked list
i.e.
before : 1 -> 2 -> 3
remove(1)
after : 1 -> 3
before : 1 -> 2 -> 3
remove(2)
after : 1 -> 2
before : 1 -> 2 -> 3
remove(0)
after : 2 -> 3
"""
if idx < 0 or idx > self.get_length():
print ("idx out of linkedlist range, idx : {}".format(idx))
return
elif idx == 0:
= self.head
current self.head = current.next
elif idx == self.get_length():
= self.head
current = 0
cur_idx while cur_idx < idx -1:
= current.next
current += 1
cur_idx next = None
current.else:
= self.head
current = 0
cur_idx while cur_idx < idx - 1:
= current.next
current += 1
cur_idx = current.next.next
next_ next = next_
current.= next_
current
def reverse(self):
"""
https://www.youtube.com/watch?v=D7y_hoT_YZI
# reverse method for the linked list
# https://www.geeksforgeeks.org/python-program-for-reverse-a-linked-list/
i.e.
before : 1 -> 2 -> 3
after : 3 -> 2 -> 1
"""
= None
prev = self.head
current while(current is not None):
= current.next
next_ next = prev
current.= current
prev = next_
current self.head = prev
// java
// LC 19
// ...
= new ListNode(0);
ListNode dummy .next = head;
dummy= dummy;
ListNode fast = dummy;
ListNode slow
for (int i = 1; i <= n+1; i++){
//System.out.println("i = " + i);
= fast.next;
fast }
// move fast and slow pointers on the same time
while (fast != null){
= fast.next;
fast = slow.next;
slow }
// NOTE here
.next = slow.next.next;
slow// ...
# python
#-------------------------
# iteration
#-------------------------
# LC 206
# V0
# IDEA : Linkedlist basics
# https://www.youtube.com/watch?v=D7y_hoT_YZI
# STEPS)
# -> STEP 1) cache "next"
# -> STEP 2) point head.next to prev
# -> STEP 3) move prev to head
# -> STEP 4) move head to "next"
class Solution(object):
def reverseList(self, head):
# edge case
if not head:
return
= None
prev while head:
# cache "next"
= head.next
tmp # point head.next to prev
next = prev
head.# move prev to head (for next iteration)
= head
prev # move head to "next" (for next iteration)
= tmp
head # NOTE!!! we return prev
return prev
// java
//---------------------------
// iteration
//---------------------------
// LC 206
// V0
public ListNode reverseList(ListNode head) {
if (head == null) {
return null;
}
= null;
ListNode _prev
while (head != null) {
/**
* NOTE !!!!
*
* 4 operations
*
* step 1) cache next
* step 2) point cur to prev
* step 3) move prev to cur
* step 4) move cur to next
*
*/
= head.next;
ListNode _next .next = _prev;
head= head;
_prev = _next;
head }
// NOTE!!! we return _prev here, since it's now "new head"
return _prev;
}
// java
//---------------------------
// recursion
//---------------------------
// LC 206
// algorithm book (labu) p.290
// IDEA : Recursive
// https://leetcode.com/problems/reverse-linked-list/editorial/
// https://github.com/yennanliu/CS_basics/blob/master/leetcode_java/src/main/java/LeetCodeJava/LinkedList/ReverseLinkedList.java
// same as above
// java
//---------------------------
// iteration
//---------------------------
// algorithm book (labu) p.298
reverse(ListNode a, Listnode b){
ListNode , cur, nxt;
ListNode pre= null;
pre = a;
cur = a;
nxt /** THE ONLY DIFFERENCE (reverse nodes VS reverse nodes in [a,b]) */
while (cur != b){
= cur.next;
nxt // reverse on each node
.next = pre;
cur// update pointer
= cur;
pre = nxt;
cur }
// return reversed nodes
return pre;
}
// java
//---------------------------
// iteration
//---------------------------
// LC 25
// algorithm book (labu) p.298
reverse(ListNode a, Listnode b){
ListNode , cur, nxt;
ListNode pre= null;
pre = a;
cur = a;
nxt /** THE ONLY DIFFERENCE (reverse first N nodes VS reverse nodes in [a,b]) */
while (cur != b){
= cur.next;
nxt // reverse on each node
.next = pre;
cur// update pointer
= cur;
pre = nxt;
cur }
// return reversed nodes
return pre;
}
reverseKGroup(ListNode head, int k){
ListNode if (head == null) return null;
// inverval [a,b] has k to-reverse elements
, b;
ListNode a= b = head;
a for (int i = 0; i < k; i++){
// not enough elements (amount < k), no need to reverse -> base case
if (b == null) return head;
= b.next;
b }
// reverse k elements
= reverse(a,b);
ListNode newHead // reverse remaining nodes, and connect with head
.next = reverseKGroup(b,k);
areturn newHead;
}
# LC 025
class Solution:
def reverseKGroup(self, head, k):
# help func
# check if # of sub nodes still > k
def check(head, k):
= 0
ans while head:
+= 1
ans if ans >= k:
return True
= head.next
head return False
# edge case
if not head:
return
= dummy = ListNode(None)
d = None
pre = curHead = head
preHead while check(curHead, k):
for _ in range(k):
# reverse linked list
= curHead.next
tmp next = pre
curHead.= curHead
pre = tmp
curHead # reverse linked list
# ???
next = pre
dummy.= preHead
dummy next = curHead
preHead.= curHead
preHead return d.next
//---------------------------
// recursion
//---------------------------
// java
// algorithm book (labu) p.293
// "postorder" node
= null;
ListNode successor
// reverse first N node (from head), and return new head
reverseN(ListNode head, int n){
ListNode if (n == 1){
// record n + 1 nodes, will be used in following steps
= head.next;
successor return head;
}
// set head.next as start point, return first n - 1 nodes
= reverseN(head.next, n-1);
ListNode last
.next.next = head;
head// connect reversed head node and following nodes
.next = successor;
headreturn last;
}
// java
//---------------------------
// recursion
//---------------------------
// algorithm book (labu) p.293
// "postorder" node
= null;
ListNode successor
// reverse first N node (from head), and return new head
reverseN(ListNode head, int n){
ListNode if (n == 1){
// record n + 1 nodes, will be used in following steps
= head.next;
successor return head;
}
// reverse nodes in index = m to index = n
reverseBetween(ListNode head, int m, int n){
ListNode // base case
if (m == 1){
return reverseN(head, n);
}
// for head.next, the op is reverse interval : [m-1, n-1]
// will trigger base case when when meet reverse start point
.next = reverseBetween(head.next, m - 1, n - 1);
headreturn head;
# LC 002
class Solution(object):
def addTwoNumbers(self, l1, l2):
"""
NOTE :
1. we init linkedlist via ListNode()
2. we NEED make extra head refer same linkedlist, since we need to return beginning of linkedlist of this func, while res will meet "tail" at the end of while loop
"""
= res = ListNode()
head = 0
plus = 0
tmp while l1 or l2:
+= plus
tmp = 0
plus if l1:
+= l1.val
tmp = l1.next
l1 if l2:
+= l2.val
tmp = l2.next
l2 if tmp > 9:
-= 10
tmp = 1
plus
next = ListNode(tmp)
res.= res.next
res = 0
tmp ### NOTE : need to deal with case : l1, l2 are completed, but still "remaining" plus
if plus != 0:
next = ListNode(plus)
res.= res.next
res #print ("res = " + str(res))
#print ("head = " + str(head))
return head.next
# LC 445 Add Two Numbers II
# V0
# IDEA : string + linked list
# DEMO
# input :
# [7,2,4,3]
# [5,6,4]
# intermedia output :
# l1_num = 7243
# l2_num = 564
class Solution:
def addTwoNumbers(self, l1, l2):
if not l1 and not l2:
return None
= 0
l1_num while l1:
= l1_num * 10 + l1.val
l1_num = l1.next
l1
= 0
l2_num while l2:
= l2_num * 10 + l2.val
l2_num = l2.next
l2
print ("l1_num = " + str(l1_num))
print ("l2_num = " + str(l2_num))
### NOTE : trick here :
# -> get int format of 2 linked list first (l1, l2)
# -> then sum them (l1_num + l2_num)
= l1_num + l2_num
lsum
= ListNode(None)
head = head
cur ### NOTE : go thrpigh the linked list int sum, append each digit to ListNode and return it
for istr in str(lsum):
next = ListNode(int(istr))
cur.= cur.next
cur # NOTE : need to return head (but not cur, since cur already meet the end of ListNode)
return head.next
// algorithm book p. 286
// java
, fast;
Listnode slow= fast = head;
slow while (fast && fast.next){
= fast.next.next;
fast = slow.next;
slow }
// slow pointer will be linked list middle point
// if element count in linked list is odd (TO VERIFY)
if (fast != null){
= slow.next;
slow }
# LC 876 Middle of the Linked List
# V0
# IDEA : fast, slow pointers + linkedlist
class Solution(object):
def middleNode(self, head):
# edge case
if not head:
return
= f = head
s while f and f.next:
# if not f:
# break
= f.next.next
f = s.next
s return s
# LC 234 : palindrome-linked-list
# V0
# IDEA : LINKED LIST -> LIST
# EXAMPLE INPUT :
# [1,2,2,1]
# WHILE GO THROUGH :
# head = ListNode{val: 2, next: ListNode{val: 2, next: ListNode{val: 1, next: None}}}
# head = ListNode{val: 2, next: ListNode{val: 1, next: None}}
# head = ListNode{val: 1, next: None}
class Solution(object):
def isPalindrome(self, head):
### NOTE : THE CONDITION
if not head or not head.next:
return True
= []
r ### NOTE : THE CONDITION
while head:
r.append(head.val)= head.next
head return r == r[::-1]
# LC 021
# V0
# IDEA : LOOP 2 LINKED LISTS
class Solution(object):
def mergeTwoLists(self, l1, l2):
if not l1 or not l2:
return l1 or l2
### NOTICE THIS
# -> we init head, and cur
# -> use cur for `link` op
# -> and return the `head.next`
= cur = ListNode(0)
head while l1 and l2:
if l1.val < l2.val:
"""
### NOTE
1) assign node to cur.next !!! (not cur)
2) assign node rather than node.val
"""
next = l1
cur.= l1.next
l1 else:
"""
### NOTE
1) assign node to cur.next !!! (not cur)
2) assign node rather than node.val
"""
next = l2
cur.= l2.next
l2 # note this
= cur.next
cur ### NOTE this (in case either l1 or l2 is remaining so we need to append one of them to cur)
next = l1 or l2
cur.### NOTICE THIS : we return head.next
return head.next
# LC 023 Merge k sorted lists
# V0
# IDEA : LC 021 Merge Two Sorted Lists + implement mergeTwoLists on every 2 linedlist
# https://github.com/yennanliu/CS_basics/blob/master/doc/cheatsheet/linked_list.md#1-1-6-reverse-nodes-in-k-group--linked-list-iteration
class Solution(object):
def mergeKLists(self, lists):
if len(lists) == 0:
return
if len(lists) == 1:
return lists[0]
= lists[0]
_init_list for _list in lists[1:]:
= self.mergeTwoLists(_init_list, _list)
tmp = tmp
_init_list return tmp
# LC 021 : https://github.com/yennanliu/CS_basics/blob/master/leetcode_python/Linked_list/merge-two-sorted-lists.py
def mergeTwoLists(self, l1, l2):
if not l1 or not l2:
return l1 or l2
= head = ListNode()
res while l1 and l2:
if l1.val < l2.val:
next = l1
res.= l1.next
l1 else:
next = l2
res.= l2.next
l2 = res.next
res
if l1 or l2:
next = l1 or l2
res.
return head.next
# LC 206
class Solution(object):
def reverseList(self, head):
# edge case
if not head:
return
= None
prev while head:
# cache "next"
= head.next
tmp # point head.next to prev
next = prev
head.# move prev to head
= head
prev # move head to "next"
= tmp
head return prev
// java
// V0-1
// IDEA: LINKED LIST OP (iteration 1)
// https://neetcode.io/solutions/reverse-linked-list-ii
// https://youtu.be/RF_M9tX4Eag?si=vTfAtfbmGwzsmtpi
public ListNode reverseBetween_0_1(ListNode head, int left, int right) {
= new ListNode(0);
ListNode dummy .next = head;
dummy= dummy, cur = head;
ListNode leftPrev
for (int i = 0; i < left - 1; i++) {
= cur;
leftPrev = cur.next;
cur }
= null;
ListNode prev for (int i = 0; i < right - left + 1; i++) {
= cur.next;
ListNode tmpNext .next = prev;
cur= cur;
prev = tmpNext;
cur }
.next.next = cur;
leftPrev.next = prev;
leftPrev
return dummy.next;
}
# LC 92 Reverse Linked List II
# V1
# IDEA : Iterative Link Reversal
# https://leetcode.com/problems/reverse-linked-list-ii/solution/
class Solution:
def reverseBetween(self, head, m, n):
# Empty list
if not head:
return None
# Move the two pointers until they reach the proper starting point
# in the list.
= head, None
cur, prev while m > 1:
= cur
prev = cur.next
cur = m - 1, n - 1
m, n
# The two pointers that will fix the final connections.
= cur, prev
tail, con
# Iteratively reverse the nodes until n becomes 0.
while n:
= cur.next
third next = prev
cur.= cur
prev = third
cur -= 1
n
# Adjust the final connections as explained in the algorithm
if con:
next = prev
con.else:
= prev
head next = cur
tail.return head
# LC 138. Copy List with Random Pointer
# V0
# IDEA :
# step 1) make 2 objects (m, n) refer to same instance (head)
# step 2) go through m, and set up the dict
# step 3) go through n, and get the random pointer via the dict we set up in step 2)
class Node(object):
def __init__(self, val, next, random):
self.val = val
self.next = next
self.random = random
class Solution:
def copyRandomList(self, head):
= dict()
dic ### NOTE : make m, and n refer to same instance (head)
= n = head
m while m:
### NOTE : the value in dict is Node type (LinkedList)
= Node(m.val)
dic[m] = m.next
m while n:
next = dic.get(n.next)
dic[n].= dic.get(n.random)
dic[n].random = n.next
n return dic.get(head)
// java
// NOTE : there is also recursive solution
// LC 138
// V2
// IDEA : Iterative with O(N) Space
// https://leetcode.com/problems/copy-list-with-random-pointer/editorial/
// Visited dictionary to hold old node reference as "key" and new node reference as the "value"
HashMap<Node, Node> visited = new HashMap<Node, Node>();
public Node getClonedNode(Node node) {
// If the node exists then
if (node != null) {
// Check if the node is in the visited dictionary
if (this.visited.containsKey(node)) {
// If its in the visited dictionary then return the new node reference from the dictionary
return this.visited.get(node);
} else {
// Otherwise create a new node, add to the dictionary and return it
this.visited.put(node, new Node(node.val, null, null));
return this.visited.get(node);
}
}
return null;
}
public Node copyRandomList_3(Node head) {
if (head == null) {
return null;
}
Node oldNode = head;
// Creating the new head node.
Node newNode = new Node(oldNode.val);
this.visited.put(oldNode, newNode);
// Iterate on the linked list until all nodes are cloned.
while (oldNode != null) {
// Get the clones of the nodes referenced by random and next pointers.
.random = this.getClonedNode(oldNode.random);
newNode.next = this.getClonedNode(oldNode.next);
newNode
// Move one step ahead in the linked list.
= oldNode.next;
oldNode = newNode.next;
newNode }
return this.visited.get(head);
}
# LC 160 Intersection of Two Linked Lists
# V0
# IDEA : if the given 2 linked list have intersection, then
# they must overlap in SOMEWHERE if we go through
# each of them in the same length
# -> e.g.
# process1 : headA -> headB -> headA ...
# process2 : headB -> headA -> headB ...
class Solution(object):
def getIntersectionNode(self, headA, headB):
if not headA or not headB:
return None
= headA, headB
p, q while p and q and p != q:
= p.next
p = q.next
q if p == q:
return p
if not p:
= headB
p if not q:
= headA
q return p
# LC 725. Split Linked List in Parts
# V0
# IDEA : LINKED LIST OP + mod op
class Solution(object):
def splitListToParts(self, head, k):
# NO need to deal with edge case !!!
# get linked list length
= 0
_len = cur = head
_head while _head:
+= 1
_len = _head.next
_head # init res
= [None] * k
res ### NOTE : we loop over k
for i in range(k):
"""
2 cases
case 1) i < (_len % k) : there is "remainder" ((_len % k)), so we need to add extra 1
-> _cnt_elem = (_len // k) + 1
case 2) i == (_len % k) : there is NO "remainder"
-> _cnt_elem = (_len // k)
"""
# NOTE THIS !!!
= (_len // k) + (1 if i < (_len % k) else 0)
_cnt_elem ### NOTE : we loop over _cnt_elem (length of each "split" linkedlist)
for j in range(_cnt_elem):
"""
3 cases
1) j == 0 (begin of sub linked list)
2) j == _cnt_elem - 1 (end of sub linked list)
3) 0 < j < _cnt_elem - 1 (middle within sub linked list)
"""
# NOTE THIS !!!
# NOTE we need keep if - else in BELOW ORDER !!
# -> j == 0, j == _cnt_elem - 1, else
if j == 0:
= cur
res[i] ### NOTE this !!! :
# -> IF (but not elif)
# -> since we also need to deal with j == 0 and j == _cnt_elem - 1 case
if j == _cnt_elem - 1: # note this !!!
# get next first
= cur.next
tmp # point cur.next to None
next = None
cur.# move cur to next (tmp) for op in next i (for i in range(k))
= tmp
cur else:
= cur.next
cur #print ("res = " + str(res))
return res
# LC 19. Remove Nth Node From End of List
# NOTE : there is (two pass algorithm) approach
# V0
# IDEA : FAST-SLOW POINTERS (One pass algorithm)
# IDEA :
# step 1) we move fast pointers n+1 steps -> so slow, fast pointers has n distance (n+1-1 == n)
# step 2) we move fast, and slow pointers till fast pointer meet the end
# step 3) then we point slow.next to slow.next.next (same as we remove n node)
# step 4) we return new_head.next as final result
class Solution(object):
def removeNthFromEnd(self, head, n):
= ListNode(0)
new_head next = head
new_head.= slow = new_head
fast for i in range(n+1):
= fast.next
fast while fast:
= fast.next
fast = slow.next
slow next = slow.next.next
slow.return new_head.next
// java
public ListNode removeNthFromEnd(ListNode head, int n) {
if (head == null){
return head;
}
if (head.next == null && head.val == n){
return null;
}
// move fast pointer only with n+1 step
// 2 cases:
// - 1) node count is even
// - 2) node count is odd
/** NOTE !! we init dummy pointer, and let fast, slow pointers point to it */
= new ListNode(0);
ListNode dummy .next = head;
dummy// NOTE here
= dummy;
ListNode fast = dummy;
ListNode slow /**
* Explanation V1:
*
* -> So we have fast, and slow pointer,
* if we move fast N steps first,
* then slow starts to move
* -> fast, slow has N step difference
* -> what's more, when fast reach the end,
* -> fast, slow STILL has N step difference
* -> and slow has N step difference with the end,
* -> so we can remove N th pointer accordingly
*
* Explanation V2:
*
*
* // NOTE !!! we let fast pointer move N+1 step first
* // so once fast pointers reach the end after fast, slow pointers move together
* // we are sure that slow pointer is at N-1 node
* // so All we need to do is :
* // point slow.next to slow.next.next
* // then we remove N node from linked list
*/
for (int i = 1; i <= n+1; i++){
//System.out.println("i = " + i);
= fast.next;
fast }
// move fast and slow pointers on the same time
while (fast != null){
= fast.next;
fast = slow.next;
slow }
// NOTE here
.next = slow.next.next;
slow// NOTE !!! we return dummy.next instead of slow
return dummy.next;
}
// java
// V0
// IDEA : get len of linkedlist, and re-point node
public ListNode removeNthFromEnd_0(ListNode head, int n) {
if (head.next == null){
return null;
}
// below op is optional
// if (head.next.next == null){
// if (n == 1){
// return new ListNode(head.val);
// }
// return new ListNode(head.next.val);
// }
// get len
int len = 0;
= head;
ListNode head_ while (head_ != null){
= head_.next;
head_ += 1;
len }
= new ListNode();
ListNode root /** NOTE !!! root_ is the actual final result */
= root;
ListNode root_
// if n == len
if (n == len){
= head.next;
head .next = head;
root= root.next;
root }
/**
* IDEA: get length of linked list,
* then if want to delete n node from the end of linked list,
* -> then we need to stop at "len - n" idx,
* -> and reconnect "len - n" idx to "len -n + 2" idx
* -> (which equals delete "n" idx node
*
*
* Consider linked list below :
*
* 0, 1, 2 , 3, 4 .... k-2, k-1, k
*
* if n = 1, then "k-1" is the node to be removed.
* -> so we find "k-2" node, and re-connect it to "k" node
*/
/** NOTE !!!
*
* idx is the index, that we "stop", and re-connect
* from idx to its next next node (which is the actual "delete" node op
*/
int idx = len - n; // NOTE !!! this
while (idx > 0){
.next = head;
root= root.next;
root = head.next;
head -= 1;
idx }
= head.next;
ListNode next .next = next;
root
return root_.next;
}
// java
public void reorderList(ListNode head) {
// Edge case: empty or single node list
if (head == null || head.next == null) {
return;
}
// Step 1: Find the middle node
= head, fast = head;
ListNode slow while (fast != null && fast.next != null) {
= slow.next;
slow = fast.next.next;
fast }
// Step 2: Reverse the second half of the list
/** NOTE !!!
*
* reverse on `slow.next` node
*/
= reverseNode_(slow.next);
ListNode secondHalf /** NOTE !!!
*
* `cut off` slow node's next nodes via point it to null node
* (if not cut off, then in merge step, we will merge duplicated nodes
*/
.next = null; // Break the list into two halves
slow
// Step 3: Merge two halves
= head;
ListNode firstHalf while (secondHalf != null) {
// NOTE !!! cache `next node` before any op
= firstHalf.next;
ListNode _nextFirstHalf = secondHalf.next;
ListNode _nextSecondHalf
// NOTE !!! point first node to second node, then point second node to first node's next node
.next = secondHalf;
firstHalf.next = _nextFirstHalf;
secondHalf
// NOTE !!! move both node to `next` node
= _nextFirstHalf;
firstHalf = _nextSecondHalf;
secondHalf }
}
// Helper function to reverse a linked list
private ListNode reverseNode_(ListNode head) {
= null;
ListNode prev while (head != null) {
= head.next;
ListNode next .next = prev;
head= head;
prev = next;
head }
return prev;
}
# LC 143. Reorder List
# V0
# IDEA : Reverse the Second Part of the List and Merge Two Sorted Lists
class Solution:
def reorderList(self, head):
if not head:
return
# find the middle of linked list [Problem 876]
# in 1->2->3->4->5->6 find 4
= fast = head
slow while fast and fast.next:
= slow.next
slow = fast.next.next
fast
# reverse the second part of the list [Problem 206]
# convert 1->2->3->4->5->6 into 1->2->3->4 and 6->5->4
# reverse the second half in-place
= None, slow
prev, curr while curr:
= curr.next
tmp
next = prev
curr.= curr
prev = tmp
curr
# merge two sorted linked lists [Problem 21]
# merge 1->2->3->4 and 6->5->4 into 1->6->2->5->3->4
= head, prev
first, second while second.next:
= first.next
tmp next = second
first.= tmp
first
= second.next
tmp next = first
second.= tmp
second
# V0'
# IDEA : Reverse the Second Part of the List and Merge Two Sorted Lists (simplified code from V1)
class Solution:
def reorderList(self, head):
if not head:
return
# find the middle of linked list [Problem 876]
# in 1->2->3->4->5->6 find 4
= fast = head
slow while fast and fast.next:
= slow.next
slow = fast.next.next
fast
# reverse the second part of the list [Problem 206]
# convert 1->2->3->4->5->6 into 1->2->3->4 and 6->5->4
# reverse the second half in-place
= None, slow
prev, curr while curr:
next, prev, curr = prev, curr, curr.next
curr.
# merge two sorted linked lists [Problem 21]
# merge 1->2->3->4 and 6->5->4 into 1->6->2->5->3->4
= head, prev
first, second while second.next:
next, first = second, first.next
first.next, second = first, second.next
second.
# V0'''
class Solution:
def reorderList(self, head):
if head is None:
return head
#find mid
= head
slow = head
fast while fast.next and fast.next.next:
= slow.next
slow = fast.next.next
fast = slow
mid
#cut in the mid
= head
left = mid.next
right if right is None:
return head
next = None
mid.
#reverse right half
= right.next
cursor next = None
right.while cursor:
next = cursor.next
next = right
cursor.= cursor
right = next
cursor
#merge left and right
= ListNode(0)
dummy while left or right:
if left is not None:
next = left
dummy.= left.next
left = dummy.next
dummy if right is not None:
next = right
dummy.= right.next
right = dummy.next
dummy return head
# LC 24. Swap Nodes in Pairs
# V0
# IDEA : LINKED LIST
# NOTE :
# 1) define 2 node via : n1, n2 = head.next, head.next.next
# 2) START THE PROCESS FROM "RIGHT HAND SIDE",
# i.e. : n1.next = n2.next ( connect n1 to next node) -> connect n2 to n1 (n2.next = n1) -> connect dummy to n2 (head.next = n2)
# 3) THEN MOVE HEAD FORWARD (head = n1)
class Solution:
def swapPairs(self, head):
if not head or not head.next:
return head
= ListNode(0)
dummy next = head
dummy.= dummy
head while head.next and head.next.next:
= head.next, head.next.next
n1, n2 next = n2.next
n1.next = n1
n2.next = n2
head.= n1
head return dummy.next
// java
// LC 369
// V1
// IDEA : LINKED LIST OP (gpt)
/**
* Step 1) reverse linked list
* Step 2) plus 1, bring `carry` to next digit if curSum > 9, ... repeat for all nodes
* Step 3) reverse linked list again
*/
public ListNode plusOne_1(ListNode head) {
if (head == null) return new ListNode(1); // Handle edge case
// Reverse the linked list
= reverseList(head);
head
// Add one to the reversed list
= head;
ListNode current int carry = 1; // Start with adding one
while (current != null && carry > 0) {
int sum = current.val + carry;
.val = sum % 10; // Update the current node value
current= sum / 10; // Calculate carry for the next node
carry if (current.next == null && carry > 0) {
.next = new ListNode(carry); // Add a new node for carry
current= 0; // No more carry after this
carry }
= current.next;
current }
// Reverse the list back to original order
return reverseList(head);
}
// Utility to reverse a linked list
private ListNode reverseList(ListNode head) {
= null;
ListNode prev = head;
ListNode current
while (current != null) {
= current.next; // Save the next node
ListNode next .next = prev; // Reverse the link
current= current; // Move prev forward
prev = next; // Move current forward
current }
return prev;
}
// java
// LC 817
// V1
// IDEA: set, linkedlist (gpt)
public int numComponents_1(ListNode head, int[] nums) {
// Convert nums array to a HashSet for O(1) lookups
Set<Integer> numsSet = new HashSet<>();
for (int num : nums) {
.add(num);
numsSet}
int count = 0;
boolean inComponent = false;
// Traverse the linked list
while (head != null) {
if (numsSet.contains(head.val)) {
// Start a new component if not already in one
if (!inComponent) {
++;
count= true;
inComponent }
} else {
// End the current component
= false;
inComponent }
= head.next;
head }
return count;
}