From 2c0a5420da8a9c787e331606124737e643f9da16 Mon Sep 17 00:00:00 2001 From: Nikita Saini Date: Sun, 23 Jun 2024 23:22:05 +0530 Subject: [PATCH 1/2] Create 0502-IPO.md add solution to the leetcode problem 0505 - IPO --- .../lc-solutions/0500-0599/0502-IPO.md | 292 ++++++++++++++++++ 1 file changed, 292 insertions(+) create mode 100644 dsa-solutions/lc-solutions/0500-0599/0502-IPO.md diff --git a/dsa-solutions/lc-solutions/0500-0599/0502-IPO.md b/dsa-solutions/lc-solutions/0500-0599/0502-IPO.md new file mode 100644 index 000000000..f07bf144a --- /dev/null +++ b/dsa-solutions/lc-solutions/0500-0599/0502-IPO.md @@ -0,0 +1,292 @@ +--- +id: IPO +title: IPO +sidebar_label: IPO +tags: + - Dynamic Programming + - Greedy Algorithm + - Priority Queue +--- + +## Problem Description + +| Problem Statement | Solution Link | LeetCode Profile | +| :------------------------------------------------------ | :------------------------------------------------------------------------- | :------------------------------------------------------ | +| [IPO](https://leetcode.com/problems/IPO/description/) | [IPO Solution on LeetCode](https://leetcode.com/problems/IPO/solutions/) | [Nikita Saini](https://leetcode.com/u/Saini_Nikita/) | + +## Problem Description + +You are given `n` projects where the ith project has a pure profit `profits[i]` and a minimum capital of `capital[i]` is needed to start it. Initially, you have `w` capital. When you finish a project, you obtain its pure profit, which is added to your total capital. + +Your goal is to pick a list of at most `k` distinct projects to maximize your final capital. + +## Constraints + +- `1 <= k <= 10^5` +- `0 <= w <= 10^9` +- `1 <= n <= 10^5` +- `0 <= profits[i] <= 10^4` +- `0 <= capital[i] <= 10^9` + +## Approach + +The problem can be approached using a combination of greedy strategy and efficient data structures: +1. **Priority Queue (Max-Heap)**: Use a max-heap to always select the project with the maximum profit that can be started with the current capital. +2. **Sorting**: Sort projects based on their capital requirements. +3. **Iterative Selection**: Iterate up to `k` times (or until no more projects can be started) to select the project with the highest profit that can be started with the current capital. + +### Solution in Different languages + +## Solution in Python + +```python +import heapq + +def findMaximizedCapital(k, w, profits, capital): + n = len(profits) + projects = sorted(zip(capital, profits)) # Sort projects by their capital requirements + available_projects = [] + idx = 0 + for _ in range(k): + while idx < n and projects[idx][0] <= w: + heapq.heappush(available_projects, -projects[idx][1]) # Max-heap for profits + idx += 1 + if available_projects: + w -= heapq.heappop(available_projects) # Add the profit from the best project + else: + break + return w + +# Example usage: +k = 2 +w = 0 +profits = [1, 2, 3] +capital = [0, 1, 1] +print(findMaximizedCapital(k, w, profits, capital)) # Output: 4 +``` + +## Solution in Java + +```java +import java.util.PriorityQueue; + +class Solution { + public int findMaximizedCapital(int k, int w, int[] profits, int[] capital) { + int n = profits.length; + int[][] projects = new int[n][2]; + for (int i = 0; i < n; i++) { + projects[i][0] = capital[i]; + projects[i][1] = profits[i]; + } + Arrays.sort(projects, (a, b) -> a[0] - b[0]); // Sort projects by their capital requirements + PriorityQueue maxHeap = new PriorityQueue<>((a, b) -> b - a); + int idx = 0; + for (int i = 0; i < k; i++) { + while (idx < n && projects[idx][0] <= w) { + maxHeap.offer(projects[idx][1]); // Max-heap for profits + idx++; + } + if (!maxHeap.isEmpty()) { + w += maxHeap.poll(); // Add the profit from the best project + } else { + break; + } + } + return w; + } +} +``` + +## Solution in C++ + +```cpp +#include +#include +#include +using namespace std; + +class Solution { +public: + int findMaximizedCapital(int k, int w, vector& profits, vector& capital) { + int n = profits.size(); + vector> projects(n); + for (int i = 0; i < n; ++i) { + projects[i] = {capital[i], profits[i]}; + } + sort(projects.begin(), projects.end()); // Sort projects by their capital requirements + priority_queue maxHeap; + int idx = 0; + for (int i = 0; i < k; ++i) { + while (idx < n && projects[idx].first <= w) { + maxHeap.push(projects[idx].second); // Max-heap for profits + ++idx; + } + if (!maxHeap.empty()) { + w += maxHeap.top(); // Add the profit from the best project + maxHeap.pop(); + } else { + break; + } + } + return w; + } +}; +``` + +## Solution in C + +```c +#include + +// Helper function to sort projects by capital requirement +int compare(const void *a, const void *b) { + int *projA = *(int **)a; + int *projB = *(int **)b; + return projA[0] - projB[0]; +} + +int findMaximizedCapital(int k, int w, int* profits, int profitsSize, int* capital, int capitalSize) { + int n = profitsSize; + int **projects = (int **)malloc(n * sizeof(int *)); + for (int i = 0; i < n; ++i) { + projects[i] = (int *)malloc(2 * sizeof(int)); + projects[i][0] = capital[i]; + projects[i][1] = profits[i]; + } + qsort(projects, n, sizeof(int *), compare); // Sort projects by their capital requirements + int idx = 0; + for (int i = 0; i < k; ++i) { + while (idx < n && projects[idx][0] <= w) { + w += projects[idx][1]; // Add the profit from the best project + ++idx; + } + if (idx == n) break; + } + for (int i = 0; i < n; ++i) { + free(projects[i]); + } + free(projects); + return w; +} +``` + +## Solution in JavaScript + +```javascript +class PriorityQueue { + constructor(comparator = (a, b) => a - b) { + this._heap = []; + this._comparator = comparator; + } + + size() { + return this._heap.length; + } + + isEmpty() { + return this.size() === 0; + } + + peek() { + return this.isEmpty() ? undefined : this._heap[0]; + } + + push(...values) { + values.forEach(value => { + this._heap.push(value); + this._siftUp(); + }); + return this.size(); + } + + pop() { + const poppedValue = this.peek(); + const bottom = this.size() - 1; + if (bottom > 0) { + this._swap(0, bottom); + } + this._heap.pop(); + this._siftDown(); + return poppedValue; + } + + _parent(idx) { + return Math.floor((idx - 1) / 2); + } + + _left(idx) { + return idx * 2 + 1; + } + + _right(idx) { + return idx * 2 + 2; + } + + _swap(i, j) { + [this._heap[i], this._heap[j]] = [this._heap[j], this._heap[i]]; + } + + _greater(i, j) { + return this._comparator(this._heap[i], this._heap[j]) < 0; + } + + _siftUp() { + let node = this.size() - 1; + while (node > 0 && this._greater(node, this._parent(node))) { + this._swap(node, this._parent(node)); + node = this._parent(node); + } + } + + _siftDown() { + let node = 0; + while ( + (this._left(node) < this.size() && this._greater(this._left(node), node)) || + (this._right(node) < this.size() && this._greater(this._right(node), node)) + ) { + let maxChild = (this._right(node) < this.size() && this._greater(this._right(node), this._left(node))) ? this._right(node) : this._left(node); + this._swap(node, maxChild); + node = maxChild; + } + } +} + +var findMaximizedCapital = function(k, w, profits, capital) { + const n = profits.length; + const projects = []; + for (let i = 0; i < n; i++) { + projects.push([capital[i], profits[i]]); + } + projects.sort((a, b) => a[0] - b[0]); // Sort projects by their capital requirements + const maxHeap = new PriorityQueue((a, b) => b - a); + let idx = 0; + for (let i = 0; i < k; i++) { + while (idx < n && projects[idx][0] <= w) { + maxHeap.push(projects[idx][1]); // Max-heap for profits + idx++; + } + if (!maxHeap.isEmpty()) { + w += maxHeap.pop(); // Add the profit from the best project + } else { + break; + } + } + return w; +}; +``` + +## Step-by-Step Algorithm + +1. **Input Parsing**: Convert input data into appropriate data structures (arrays, lists, or vectors). +2. **Sorting**: Sort projects based on their capital requirements. +3. **Priority Queue Initialization**: Initialize a max-heap (priority queue) to keep track of the most profitable projects that can be started with the current capital. +4. **Iterative Selection**: + - For up to `k` times, iterate through the sorted projects. + - Push all feasible projects (capital requirement <= current capital) into the max-heap. + - If the max-heap is not empty, pop the project with the maximum profit and add its profit to the current capital. + - Break the loop if no more projects can be started. +5. **Return Result**: Return the current capital after selecting up to `k` projects. + +## Conclusion + +The provided solutions efficiently solve the problem of selecting at most `k` projects to maximize capital using a combination of greedy strategy and priority queues. This approach ensures that the solution is optimal and runs within acceptable time limits for the given constraints. From 57cd2391c76c559cf2ade013bb842149990fe8c8 Mon Sep 17 00:00:00 2001 From: Nikita Saini Date: Sun, 23 Jun 2024 23:46:30 +0530 Subject: [PATCH 2/2] Update 0502 - IPO.md --- dsa-solutions/lc-solutions/0500-0599/0502-IPO.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dsa-solutions/lc-solutions/0500-0599/0502-IPO.md b/dsa-solutions/lc-solutions/0500-0599/0502-IPO.md index f07bf144a..5aaaa99b7 100644 --- a/dsa-solutions/lc-solutions/0500-0599/0502-IPO.md +++ b/dsa-solutions/lc-solutions/0500-0599/0502-IPO.md @@ -282,7 +282,7 @@ var findMaximizedCapital = function(k, w, profits, capital) { 3. **Priority Queue Initialization**: Initialize a max-heap (priority queue) to keep track of the most profitable projects that can be started with the current capital. 4. **Iterative Selection**: - For up to `k` times, iterate through the sorted projects. - - Push all feasible projects (capital requirement <= current capital) into the max-heap. + - Push all feasible projects (capital requirement <= current capital) into the max-heap. - If the max-heap is not empty, pop the project with the maximum profit and add its profit to the current capital. - Break the loop if no more projects can be started. 5. **Return Result**: Return the current capital after selecting up to `k` projects.