Skip to content

Commit

Permalink
Merge Plis (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
amitsuthar69 authored Oct 12, 2023
1 parent 95b42f1 commit b81a8e9
Show file tree
Hide file tree
Showing 19 changed files with 613 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
## KOKO Eating Bananas

**Problem Statement:** A monkey is given `n` piles of bananas, whereas the `ith` pile has `a[i]` bananas. An integer `h` is also given, which denotes the time (in hours) for all the bananas to be eaten.

Each hour, the monkey chooses a non-empty pile of bananas and eats `k` bananas. If the pile contains less than `k` bananas, then the monkey consumes all the bananas and won’t eat any more bananas in that hour.

Find the minimum number of bananas `k` to eat per hour so that the monkey can eat all the bananas within `h` hours.

---

### Examples

Example 1:
Input Format: N = 4, a[] = {7, 15, 6, 3}, h = 8
Result: 5
Explanation: If Koko eats 5 bananas/hr, he will take 2, 3, 2, and 1 hour to eat the piles accordingly. So, he will take 8 hours to complete all the piles.

---

Example 2:
Input Format: N = 5, a[] = {25, 12, 8, 14, 19}, h = 5
Result: 25
Explanation: If Koko eats 25 bananas/hr, he will take 1, 1, 1, 1, and 1 hour to eat the piles accordingly. So, he will take 5 hours to complete all the piles.

---

Before moving on to the solution, let’s understand how Koko will eat the bananas. Assume, the given array is {3, 6, 7, 11} and the given time i.e. h is 8.

First of all, Koko cannot eat bananas from different piles. He should complete the pile he has chosen and then he can go for another pile.
Now, Koko decides to eat 2 bananas/hour. So, in order to complete the first he will take
3 / 2 = 2 hours. Though mathematically, he should take 1.5 hrs but it is clearly stated in the question that after completing a pile Koko will not consume more bananas in that hour. So, for the first pile, Koko will eat 2 bananas in the first hour and then he will consume 1 banana in another hour.

From here we can conclude that we have to take ceil of (3/2). Similarly, we will calculate the times for other piles.

1st pile: ceil(3/2) = 2 hrs
2nd pile: ceil(6/2) = 3 hrs
3rd pile: ceil(7/2) = 4 hrs
4th pile: ceil(11/2) = 6 hrs

Koko will take 15 hrs in total to consume all the bananas from all the piles.

---

**Observation**: Upon observation, it becomes evident that the maximum number of bananas (represented by 'k') that Koko can consume in an hour is obtained from the pile that contains the largest quantity of bananas. Therefore, the maximum value of 'k' corresponds to the maximum element present in the given array.

So, our answer i.e. the minimum value of ‘k’ lies between 1 and the maximum element in the array i.e. max(a[]).

---

### Solution :

```cpp
#include <bits/stdc++.h>
using namespace std;

long long calculateTotalHours(vector<int> &v, long long hourly) {
long long totalH = 0;
int n = v.size();
for (int i = 0; i < n; i++) {
totalH += (v[i] + hourly - 1) / hourly;
}
return totalH;
}

long long minimumRateToEatBananas(vector<int> &v, long long h) {
long long low = 1, high = INT_MAX;

while (low < high) {
long long mid = low + (high - low) / 2;
long long totalH = calculateTotalHours(v, mid);

if (totalH <= h) {
high = mid;
} else {
low = mid + 1;
}
}
return low;
}
```
---
### Explanation :
1. `calculateTotalHours` :
This function calculates the total hours required to eat all the bananas at a given hourly rate. It uses integer division and rounds up to the nearest integer using `(v[i] + hourly - 1) / hourly`.
2. `minimumRateToEatBananas` :
This function performs a **binary search** to find the minimum hourly rate required to eat all the bananas within h hours. It initializes a `low` rate as 1 and a `high` rate as a large integer.
The binary search continues until low is less than high, and it updates the `mid` rate within this range.
It then calculates the total hours required at the mid rate using the calculateTotalHours function. If the total hours are less than or equal to h, it updates high to mid, effectively searching in the lower half of the range; otherwise, it updates low to mid + 1, searching in the upper half.
---
The expression `(v[i] + hourly - 1) / hourly` with an example:
Suppose we have the following values:
v[i] (the number of bananas to eat) = 12
hourly (the hourly rate at which we can eat) = 5
Using the expression `(v[i] + hourly - 1) / hourly`:
(12 + 5 - 1) / 5
(16) / 5
3.2
Now, let's break it down:
12 + 5 - 1 equals 16. This step ensures that we add hourly - 1 to the numerator, which is necessary to ensure rounding up.
16 / 5 equals 3.2. This is the result of dividing the numerator (16) by the denominator (5).
In this example, the result of `(v[i] + hourly - 1) / hourly` is 3.2. Since we want to round up to the nearest integer (**because you can't eat a fraction of a banana**), this value would be considered as 4 hours required to eat 12 bananas at a rate of 5 bananas per hour.
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
# Linked Lists.

**WHAT?** : It is a Linear Data Structure, which is made up of collection of nodes. For example consider a capsule having two parts. Each part is made up of nodes, The first node is the "DATA", and the second node is the "Address of the next NODE". A linked list ends by pointing a "NULL Pointer".
How a Linked List looks :<br>
`[DATA | ADDRESS ]->[ DATA | ADDRESS ]->[ DATA | NULL ]`

---

**How a Linked List looks :**

```
[DATA | ADDRESS]->[DATA | ADDRESS]->[DATA | NULL]
^ ^
head tail
```

---

**WHY?** : Think if you have an array of 10 size, so can we change its size on run time ? NO A Vector, when same value is inserted to it, it doubles its size and additional memory gets wasted, hence a vector is not an optimal data structure. Unlike these two, size of linked list can grow or shrink on run time, hence no memory waste.

Expand Down Expand Up @@ -31,21 +41,36 @@ class Node {

int main() {
Node *node1 = new Node(10);
cout << node1->data << endl; // prints the data i.e, 10.
cout << node1->nextNode << endl; // prints NULL address 0x0.
cout << node1->data << endl; // prints the data i.e, 10.
cout << node1->nextNode << endl; // prints NULL address.
return 0;
}
```

---

`Node* node1 = new Node();`

/*
Node* node1 = new Node();
The line of code is allocating memory for a new object of the class named "Node"
on the heap and assigning the address of the object to a pointer variable named
"node1". The "new" operator dynamically allocates memory for the object and
returns a pointer to the allocated memory. The parentheses after "Node()" call
the default constructor of the class or struct to initialize the object. The
result of this line of code is that you now have a dynamically allocated object
of the "Node" class or struct, and you can access its member variables and
functions through the "node1" pointer.
*/
This line of code is allocating memory for a new object of the class named "Node" on the heap and assigning the address of the object to a pointer variable named
"node1".

The "new" operator dynamically allocates memory for the object and returns a pointer to the allocated memory.

The parentheses after "Node()" call the default constructor of the class or struct to initialize the object.

The result of this line of code is that we now have a dynamically allocated object of the "Node" class, and we can access its member variables and functions through the "node1" pointer.

---

### Traverse and print linked list :

```cpp
void printLinkedList(Node *&head) {
Node *temp = head;
while (temp != NULL) {
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}
```
136 changes: 136 additions & 0 deletions Data-Structures/Linear-Data-Structures/Linked-List/02-insertion.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
## Insertion in a Linked List.

### 1. Insertion at head

**Steps :**

1. Make a `void` function which accepts a reference to a head pointer and a data as parameter.
2. Make a new temporary Node which accepts the data parameter.
3. Then point the temp node's next pointer to the current head.
4. Finally temp becomes our new head pointer.

---

### 2. Insertion at tail

**Steps :**

1. Make a `void` function which accepts a reference to a tail pointer and a data as parameter.
2. Make a new temporary Node which accepts the data parameter.
3. Then point the tail node's next pointer to the temp node.
4. Finally temp becomes our new tail pointer.

---

### 2. Insertion at any position

**Steps :**

1. Make a `void` function which accepts a reference to head & tail pointer and a position & data as parameter.
2. Make a temp node which'll initially point to head.
3.
4.
---

### Implementation :

```cpp
#include <bits/stdc++.h>
#include <cstddef>
using namespace std;

class Node {
public:
int data;
Node *next;

Node(int data) {
this->data = data;
this->next = NULL;
}
};

void insertAtHead(Node *&head, int data) {
Node *temp = new Node(data);
temp->next = head;
head = temp;
}

void insertAtTail(Node *&tail, int data) {
Node *temp = new Node(data);
tail->next = temp;
tail = temp;
}

void insertAtPosition(Node *&head, Node *&tail, int pos, int data) {
Node *temp = head;
int cnt = 1;

// if inserting at first pos
if (pos == 1) {
insertAtHead(head, data);
return;
}

// if inserting at last pos
if (temp->next == NULL) {
insertAtTail(tail, data);
return;
}

while (cnt < pos - 1) {
temp = temp->next;
cnt++;
}

Node *nodeToInsert = new Node(data);
nodeToInsert->next = temp->next;
temp->next = nodeToInsert;
}

void printLinkedList(Node *&head) {
Node *temp = head;
while (temp != NULL) {
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}

int main() {
Node *node1 = new Node(10);

// create head and tail pointer.
Node *head = node1;
Node *tail = node1;

cout << "Initial List : ";
printLinkedList(head);

insertAtHead(head, 12);

cout << "List after insertion at head : ";
printLinkedList(head);

insertAtTail(tail, 13);

cout << "List after insertion at tail : ";
printLinkedList(head);

insertAtPosition(head, tail, 3, 14);

cout << "List after insertion at 3rd position : ";
printLinkedList(head);
return 0;
}
```
```
Output :
Initial List : 10
List after insertion at head : 12 10
List after insertion at tail : 12 10 13
List after insertion at 3rd position : 12 10 14 13
```
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
## Reverse a Linked List

### Approach :

1. Initialize prev to nullptr and current to the head of the original linked list.
2. Enter a while loop that terminates when current is nullptr.
3. Inside the while loop, do the following:
- Store the next node in the original linked list in next.
- Update the next pointer of the current node to point to the previous node.
- Update the prev pointer to point to the current node.
- Update the current pointer to point to the next node.
4. Return prev, which is now the head of the reversed linked list.

---

### Imlementation :

```cpp
#include <bits/stdc++.h>
using namespace std;

template <typename T> class LinkedListNode {
public:
T data;
LinkedListNode<T> *next;
LinkedListNode(T data) {
this->data = data;
this->next = NULL;
}
};

// Solution :-
LinkedListNode<int> *reverseLinkedList(LinkedListNode<int> *head) {

LinkedListNode<int> *prev = nullptr;
LinkedListNode<int> *current = head;
LinkedListNode<int> *next = nullptr;

while (current != nullptr) {
next = current->next;
current->next = prev;
prev = current;
current = next;
}
return prev;
}

int main() { return 0; }
```
Loading

0 comments on commit b81a8e9

Please sign in to comment.