diff --git a/Topic2_LinkedList/dkhien/01ReverseLinkedList.java b/Topic2_LinkedList/dkhien/01ReverseLinkedList.java new file mode 100644 index 0000000..04b0f0a --- /dev/null +++ b/Topic2_LinkedList/dkhien/01ReverseLinkedList.java @@ -0,0 +1,30 @@ +// Time Complexity: O(n) +// Space Complexity: O(1) + +class Solution { + public ListNode reverseList(ListNode head) { + if (head == null) return null; + if (head.next == null) return head; + + ListNode newHead = new ListNode(); + newHead.next = null; + + while (head.next != null) { + // Copy value to current node of the new list + newHead.val = head.val; + + // Create the next node + ListNode next = new ListNode(); + next.val = head.next.val; + + // Connect next node to current node (next -> current) to reverse + next.next = newHead; + + // Iterate + newHead = next; + head = head.next; + } + + return newHead; + } +} \ No newline at end of file diff --git a/Topic2_LinkedList/dkhien/02MergeTwoSortedLists.java b/Topic2_LinkedList/dkhien/02MergeTwoSortedLists.java new file mode 100644 index 0000000..2f42424 --- /dev/null +++ b/Topic2_LinkedList/dkhien/02MergeTwoSortedLists.java @@ -0,0 +1,33 @@ +// Time Complexity: O(n) +// Space Complexity: O(1) + +class Solution { + public ListNode mergeTwoLists(ListNode list1, ListNode list2) { + ListNode result = new ListNode(); + ListNode current = result; + + while (list1 != null && list2 != null) { + // Choose the smaller value to add to the result list + if (list1.val <= list2.val) { + current.next = list1; + list1 = list1.next; + } else { + current.next = list2; + list2 = list2.next; + } + + // Iterate + current = current.next; + } + + // Add the remaining nodes to the result list + if (list1 != null) { + current.next = list1; + } else if (list2 != null) { + current.next = list2; + } + + return result.next; + + } +} \ No newline at end of file diff --git a/Topic2_LinkedList/dkhien/03ReorderList.java b/Topic2_LinkedList/dkhien/03ReorderList.java new file mode 100644 index 0000000..af676bb --- /dev/null +++ b/Topic2_LinkedList/dkhien/03ReorderList.java @@ -0,0 +1,37 @@ +// Time Complexity: O(n) +// Space Complexity: O(n) + +class Solution { + public void reorderList(ListNode head) { + List nodeList = new ArrayList<>(); + ListNode temp = head; + + while (temp != null) { + nodeList.add(temp); + temp = temp.next; + } + + // Traverse half of the list + for (int i = 0; i < nodeList.size() / 2; i++) { + ListNode node = nodeList.get(i); + + // The next node to link to should have index size - 1 - i + ListNode nextNode = nodeList.get(nodeList.size() - 1 - i); + + if (i == nodeList.size() / 2 - 1 && nodeList.size() % 2 == 0) { + // If the list has even number of nodes, the next node of the middle node should be null + nextNode.next = null; + } else if (i == nodeList.size() / 2 - 1 && nodeList.size() % 2 != 0) { + // If the list has odd number of nodes, the next node of the middle node should be the last node + nextNode.next = node.next; + nextNode.next.next = null; + } else { + // Normal case + nextNode.next = node.next; + } + + // Link the current node to the next node + node.next = nextNode; + } + } +} \ No newline at end of file diff --git a/Topic2_LinkedList/dkhien/04RemoveNthNodeFromEndOfList.java b/Topic2_LinkedList/dkhien/04RemoveNthNodeFromEndOfList.java new file mode 100644 index 0000000..9ee4ac8 --- /dev/null +++ b/Topic2_LinkedList/dkhien/04RemoveNthNodeFromEndOfList.java @@ -0,0 +1,29 @@ +// Time Complexity: O(n) +// Space Complexity: O(1) + +class Solution { + public ListNode removeNthFromEnd(ListNode head, int n) { + if (head == null || head.next == null) return null; + ListNode ptr1 = head; + ListNode ptr2 = head; + + // ptr2 starts first, n steps ahead of ptr1 + for (int i = 0; i < n; i++) { + if (ptr2.next == null) { + return head.next; + } + ptr2 = ptr2.next; + } + + // Move ptr1 and ptr2 until ptr2 reaches the end + while (ptr2.next != null) { + ptr1 = ptr1.next; + ptr2 = ptr2.next; + } + + // ptr1 should now be at the (n-1)th node from the end -> remove the next node + ptr1.next = ptr1.next.next; + + return head; + } +} \ No newline at end of file diff --git a/Topic2_LinkedList/dkhien/05CopyListWithRandomPointer.java b/Topic2_LinkedList/dkhien/05CopyListWithRandomPointer.java new file mode 100644 index 0000000..791e2a3 --- /dev/null +++ b/Topic2_LinkedList/dkhien/05CopyListWithRandomPointer.java @@ -0,0 +1,46 @@ +// Time Complexity: O(n) +// Space Complexity: O(n) + +class Solution { + public Node copyRandomList(Node head) { + if (head == null) return null; + + // Map original node to its clone + Map originalToClone = new HashMap<>(); + Node res = new Node(0); + Node dummy = res; + + // Idea: Clone the list linearly and avoid duplicate cloning by using a map + while (head != null) { + // Clone next node, if in map use the existing clone + Node nextClone; + if (originalToClone.containsKey(head)) { + nextClone = originalToClone.get(head); + } else { + nextClone = new Node(head.val); + originalToClone.put(head, nextClone); + } + + dummy.next = nextClone; + + // Clone random node, if in map use the existing clone + Node randomClone = null; + if (head.random != null) { + if (originalToClone.containsKey(head.random)) { + randomClone = originalToClone.get(head.random); + } else { + randomClone = new Node(head.random.val); + originalToClone.put(head.random, randomClone); + } + } + + dummy.next.random = randomClone; + + // Iterate + dummy = nextClone; + head = head.next; + } + + return res.next; + } +} \ No newline at end of file diff --git a/Topic2_LinkedList/dkhien/06AddTwoNumbers.java b/Topic2_LinkedList/dkhien/06AddTwoNumbers.java new file mode 100644 index 0000000..1e56e0d --- /dev/null +++ b/Topic2_LinkedList/dkhien/06AddTwoNumbers.java @@ -0,0 +1,48 @@ +// Time Complexity: O(n) +// Space Complexity: O(1) + +class Solution { + public ListNode addTwoNumbers(ListNode l1, ListNode l2) { + ListNode dummy = new ListNode(); + ListNode current = dummy; + int carry = 0; + + // Idea: Add each digit like in elementary school + while (true) { + + // Calculate the sum of the current digits + // If one of the lists is null, the value of that list is 0 + int sum; + if (l1 == null && l2 != null) { + sum = l2.val + carry; + l2 = l2.next; + } else if (l1 != null && l2 == null) { + sum = l1.val + carry; + l1 = l1.next; + } else if (l1 != null && l2 != null) { + sum = l1.val + l2.val + carry; + l1 = l1.next; + l2 = l2.next; + } else { + break; + } + + // Calculate the carry and the value of the current digit + carry = sum / 10; + sum %= 10; + + // Create a new node and link it to the result list + ListNode res = new ListNode(sum); + current.next = res; + current = res; + } + + // Add the last carry if any + if (carry > 0) { + ListNode carryNode = new ListNode(carry); + current.next = carryNode; + } + + return dummy.next; + } +} \ No newline at end of file diff --git a/Topic2_LinkedList/dkhien/07LinkedListCycle.java b/Topic2_LinkedList/dkhien/07LinkedListCycle.java new file mode 100644 index 0000000..6cd0e3f --- /dev/null +++ b/Topic2_LinkedList/dkhien/07LinkedListCycle.java @@ -0,0 +1,22 @@ +// Time Complexity: O(n) +// Space Complexity: O(1) + +public class Solution { + public boolean hasCycle(ListNode head) { + if (head == null) + return false; + ListNode slow = head; + ListNode fast = head; + + // Idea: The fast pointer will surely meet the slow pointer if there is a cycle + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + if (slow == fast) { + return true; + } + } + + return false; + } +} \ No newline at end of file