LeetCode
This page is a collection of LeetCode problems I did.
For more detailed explanations on data structures and algorithms, see this page.
338. Counting Bits
class Solution: def countBits(self, n: int) -> List[int]: dp = [0] * (n + 1) for i in range(n + 1): dp[i] = dp[i >> 1] + (i & 1) return dpThe number of 1’s in i is just the number of 1’s in i >> 1, plus 1 if its last bit is 1.
143. Reorder List
class Solution: def reorderList(self, head: Optional[ListNode]) -> None: slow, fast = head, head.next while fast and fast.next: slow, fast = slow.next, fast.next.next # now slow is the last node in the first half; # cut the linked list by pointing slow's next to None fst = head snd, slow.next = slow.next, None
prev, curr = None, snd while curr: curr.next, prev, curr = prev, curr, curr.next snd = prev
while snd: fst.next, snd.next, fst, snd = snd, fst.next, fst.next, snd.nextFind the middle node to cut the linked list into two halves, reverse the second half, and merge the two halves.
19. Remove Nth Node From End of List
class Solution: def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]: dummy = ListNode(next=head) left, right = dummy, dummy for _ in range(n): right = right.next while right.next: left, right = left.next, right.next left.next = left.next.next return dummy.nextKeep a gap of n between the two pointers, advance both until right hits the end, and the node after left is the one to delete. The dummy head makes deleting the head itself a normal case.
57. Insert Interval
class Solution: def insert( self, intervals: List[List[int]], newInterval: List[int] ) -> List[List[int]]: ans = [] toInsert = newInterval inserted = False for interval in intervals: if interval[1] < toInsert[0]: ans.append(interval) elif interval[0] > toInsert[1]: if not inserted: ans.append(toInsert) inserted = True ans.append(interval) # overlap, update the interval to insert else: toInsert[0] = min(toInsert[0], interval[0]) toInsert[1] = max(toInsert[1], interval[1])
if not inserted: ans.append(toInsert)
return ansWhen passing through intervals, there are three phases: adding intervals before toInsert (initially newInterval), merging overlapping intervals to update toInsert, and finally adding toInsert and all intervals after it.
56. Merge Intervals
class Solution: def merge(self, intervals: List[List[int]]) -> List[List[int]]: intervals.sort() ans = [] toInsert = intervals[0] for interval in intervals: if toInsert[1] < interval[0]: # no overlap, can't merge anymore, add to result list ans.append(toInsert) toInsert = interval else: # overlap, merge toInsert[1] = max(toInsert[1], interval[1]) ans.append(toInsert) return ansSort intervals so the start values are non-decreasing, then iterate over it: merge intervals until we can’t, add the merged interval to the result list, and repeat.