Skip to content

Commit

Permalink
add2LLs (#36)
Browse files Browse the repository at this point in the history
  • Loading branch information
amitsuthar69 authored Dec 11, 2023
1 parent 43bd914 commit b2f110b
Show file tree
Hide file tree
Showing 3 changed files with 241 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
## Add two Non-Zero Linked Lists

We are given two non-empty linked lists representing two non-negative integers.
The digits are stored in **reverse order**, and each of their nodes contains a single digit.
Add the two numbers and **return the sum as a linked list**.
We may assume the two numbers do not contain any leading zero, except the number 0 itself.

(Don't get panic by looking at reverse order, cause even with usual addition, we always start from unit's place.)

---

### Algorithm

Let's break this problem down into 5 parts, **initial setup, traversal, calculation, building sum LL, The Last carry.**

1. Initial setup :
- We are provided with two heads of LLs, So we will create 2 temporary pointers `t1` and `t2` pointing at respective head nodes.
- We'll create a `dummyNode` with some random value to track the head of newly formed LL. Also we'll maintain a `curr` pointer to track current sum LL nodes.
- We'll create a variable to store carry.
2. Traversal:
- Inorder to add each node, we'll need to traverse both the LLs unless we reach `NULL`.
3. Calculation :
- For each node, we'll create a new `sum` variable which is initially assigned with `carry`.
- If any of the `t1` or `t2` is a valid node, we'll add their vules into `sum` variable.
- To store the sum in a LL node, we'll then create a new Node and store the (%10) of sum. By this, we'll be able to seperate the unit's digit of our sum if it is >10.
- Then we'll extract the carry from the sum by dividing sum by 10.
4. Builing the sum LL :
- Once we've a node ready which holds the sum, we'll now append this node to `dummyNode`. With the help of `curr` pointer, we'll build the LL.
- Once we've added the `sumNode`, we'll now move ahead in both the LLs.
5. Check for carry :
- Once we are done adding the LLs, still we need to check if we've some value in our carry variable, if so, create a new node for carry and append it in the sum LL.

In the end, return `dummyNode`'s next as a head for new sum LL.

---

### Implementation

```cpp
Node* addTwoNumbers(Node* h1, Node* h2){
// setup
Node* t1 = h1;
Node* t2 = h2;
Node* dummyNode = new Node(-1);
Node* curr = dummyNode;
int carry = 0;

// traveral
while (t1 || t2) {
// calculation
int sum = carry;
if (t1) sum += t1->data;
if (t2) sum += t2->data;
Node* sumNode = new Node(sum%10);
carry = sum/10;

// build the new LL
curr->next = sumNode;
curr = sumNode;
// move ahead
t1 = (t1 != nullptr) ? t1->next : nullptr;
t2 = (t2 != nullptr) ? t2->next : nullptr;
}
// append left over carry
if (carry) {
Node* carryNode = new Node(carry);
curr->next = carryNode;
}

// return new head
return dummyNode->next;
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
## Segrregate Odd Even Nodes of a LL.

Given the head of a singly linked list, group all the nodes with odd indices together followed by the nodes with even indices, and return the reordered list.

**The first node is considered odd, and the second node is even, and so on.**

Note that the relative order inside both the even and odd groups should remain as it was in the input.

Expected TC: O(N), SC: O(1)

---

### Algorithm

**Brute Force (Data replacement)**

We can traverse the LL twice by jumping on alternate nodes, and store the elements into a list. Then again traversing the LL but this time assigning the segrregated values to LL.

But then we end up with a TC of O(2N) {N/2 for each alternate jump and N for data re-assignment.} and a SC of O(N) for the list which is not acceptable.

**Optimal (Pointer swapping)**

1. Assign the head node to a odd and next node to an even pointer.
2. Also point an another temporary pointer just to know where did the first even node was.
3. The idea of alternate jumps would be same, but this time it would be done in single traversal and the traversal will stop when the even node reaches the `nullptr` or points to it.
4. During traversal, point the odd nodes's next to its next's next so that the even node in between is skipped and move the odd pointer ahead. Do it for the even node as well.
5. Once all the odd and even indexed nodes are connected, connect the last odd node to our temporarily created pointer to connect the odd LL with even LL.
6. return the head.

---

### Implementation

```cpp
Node* oddEvenNodes(Node* head){
Node* odd = head;
Node* even = head->next;
Node* evenNode = head->next; // memoization
while (even != nullptr && even->next != nullptr){
odd->next == odd->next->next;
odd = odd->next;
even->next = even->next->next;
even = even->next;
}
odd->next = evenNode;
return head;
}
```
---
### Demonstration
![oddEvenSegrre](https://github.com/amitsuthar69/assets/blob/main/linked-lists/oddEvensegrregate.png?raw=true)
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
## Sort the 0s, 1s and 2s in the given LL

Given a LL of N nodes, where each node has an integer value that can be 0, 1, or 2. You need to sort the linked list in non-decreasing order and the return the head of the sorted list.

**Expected TC O(N), SC O(1)**

---

### Algorithm

**Brute Force (Data replacement)**

1. Create 3 variables to keep the count of 0s, 1s and 2s in the LL.
2. Traverse through the LL, increase the count of those 3 variables as you found them in LL.
3. Once traversed the LL entirely, come back to head and start another traversal.
4. In this traversal, re-assign each node's data based on the availability of 0s, 1s and 2s.
5. Return the head.

- **TC O(2N), SC O(1)**

**Implementation**

```cpp
// Brute force
Node* sort012(Node* head) {
int cont0 = 0, count1 = 0, count2 = 0;
Node* temp = head;
while(temp != nullptr){
if(temp->data == 0) count0++;
else if(temp->data == 1) count1++;
else count2++;
temp = temp->next;
}
temp = head;
while(temp != nullptr){
if (count0) {
temp->data = 0;
count0--;
}
else if (count1) {
temp->data = 1;
count1--;
}
else {
temp->data = 2;
count2--;
}
temp = temp->next;
}
return head;
}
```
---
**Optimal Solution (Dutch National Flag algorithm)**
1. Initialize three dummy nodes and pointers for each category (0, 1, 2). Let `zeroHead`, `oneHead`, and `twoHead` be dummy nodes. Create `zero`, `one`, and `two` pointers to the last nodes for 0s, 1s, and 2s.
2. Traverse the original linked list using a temporary pointer `temp`.
3. For each traversal :
Check the value of `temp->data`.
If it's 0, append temp to the end of the 0s list by pointing zero's next to temp and update the zero pointer.
If it's 1, append temp to the end of the 1s list by pointing one's next to temp and update the one pointer.
If it's 2, append temp to the end of the 2s list by pointing two's next to temp and update the two pointer.
4. After the traversal, connect the three LLs. **To connect 0s with 1s, first check if 1s exist, else connect with 2s.**
5. Update the head of new sorted list and delete all the dummy nodes.
6. Return new head.
**Implementation**
```cpp
// optimal
Node* sortList(Node* head) {
Node* zeroHead = new Node(-1);
Node* oneHead = new Node(-1);
Node* twoHead = new Node(-1);
Node* zero = zeroHead;
Node* one = oneHead;
Node* two = twoHead;
Node* temp = head;
while (temp != nullptr) {
if (temp->data == 0) {
zero->next = temp;
zero = temp;
} else if (temp->data == 1) {
one->next = temp;
one = temp;
} else {
two->next = temp;
two = temp;
}
temp = temp->next;
}
zero->next = oneHead->next ? oneHead->next : twoHead->next;
one->next = twoHead->next;
two->next = nullptr;
Node* newHead = zeroHead->next;
delete zeroHead; // Free the dummy nodes
delete oneHead;
delete twoHead;
return newHead;
}
```

0 comments on commit b2f110b

Please sign in to comment.