502. IPO

Suppose LeetCode will start its IPO soon. In order to sell a good price of its shares to Venture Capital, LeetCode would like to work on some projects to increase its capital before the IPO. Since it has limited resources, it can only finish at most k distinct projects before the IPO. Help LeetCode design the best way to maximize its total capital after finishing at most k distinct projects.

You are given n projects where the i t h i^{th} 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 will obtain its pure profit and the profit will be added to your total capital.

Pick a list of at most k distinct projects from given projects to maximize your final capital, and return the final maximized capital.

The answer is guaranteed to fit in a 32-bit signed integer.
 

Example 1:
Example 2:
Constraints:
  • 1 < = k < = 1 0 5 1 <= k <= 10^5 1<=k<=105
  • 0 < = w < = 1 0 9 0 <= w <= 10^9 0<=w<=109
  • n == profits.length
  • n == capital.length
  • 1 < = n < = 1 0 5 1 <= n <= 10^5 1<=n<=105
  • 0 < = p r o f i t s [ i ] < = 1 0 4 0 <= profits[i] <= 10^4 0<=profits[i]<=104
  • 0 < = c a p i t a l [ i ] < = 1 0 9 0 <= capital[i] <= 10^9 0<=capital[i]<=109

From: LeetCode
Link: 502. IPO


Solution:

Ideas:

1. Struct Definition (Project):

  • A simple structure to hold the profit and capital required for each project.

2. Sorting Projects (qsort and cmp):

  • The array of Project structures is sorted by the capital required to start the project. This allows us to efficiently iterate over the projects in ascending order of the capital required.

3. Heap Operations (siftUp, siftDown, heapPush, heapPop):

  • These functions implement a max heap, which is a complete binary tree where the value of each node is greater than or equal to the values of its children. This property makes it easy to always extract the maximum profit project available.

4. Algorithm Implementation (findMaximizedCapital function):

  • The function takes the number of projects to select (k), the initial capital (w), and arrays of profits and capitals for each project.
  • After sorting the projects by capital required, the function iterates up to k times, each time selecting the most profitable project that can be afforded with the current capital.
  • In each iteration:
    • Projects that can be started with the current capital are added to the heap.
    • The project with the highest profit is popped from the heap, and its profit is added to the capital.
      The iteration stops if no more projects can be started or if the number of projects reaches k.

5. Maximizing Capital:

  • With each project completed, the profit is added to the current capital, thus increasing the chances of being able to afford more expensive, and potentially more profitable, projects.
  • The goal is to finish the loop with the maximum possible capital after completing up to k projects.
Code:
typedef struct {
    int profit;
    int capital;
} Project;

int cmp(const void *a, const void *b) {
    Project *projA = (Project *)a;
    Project *projB = (Project *)b;
    return projA->capital - projB->capital;
}

void swap(int *a, int *b) {
    int t = *a;
    *a = *b;
    *b = t;
}

void siftUp(int *heap, int start, int end) {
    int child = end;
    while (child > start) {
        int parent = (child - 1) / 2;
        if (heap[parent] < heap[child]) {
            swap(&heap[parent], &heap[child]);
            child = parent;
        } else {
            return;
        }
    }
}

void siftDown(int *heap, int start, int end) {
    int root = start;
    while ((root * 2 + 1) <= end) {
        int child = root * 2 + 1;
        int swapIdx = root;
        if (heap[swapIdx] < heap[child]) {
            swapIdx = child;
        }
        if (child + 1 <= end && heap[swapIdx] < heap[child + 1]) {
            swapIdx = child + 1;
        }
        if (swapIdx == root) {
            return;
        } else {
            swap(&heap[root], &heap[swapIdx]);
            root = swapIdx;
        }
    }
}

void heapPush(int *heap, int *size, int value) {
    heap[*size] = value;
    siftUp(heap, 0, *size);
    *size += 1;
}

int heapPop(int *heap, int *size) {
    int result = heap[0];
    *size -= 1;
    heap[0] = heap[*size];
    siftDown(heap, 0, *size - 1);
    return result;
}

int findMaximizedCapital(int k, int w, int* profits, int profitsSize, int* capital, int capitalSize) {
    Project *projects = (Project *)malloc(sizeof(Project) * profitsSize);
    for (int i = 0; i < profitsSize; i++) {
        projects[i].profit = profits[i];
        projects[i].capital = capital[i];
    }

    qsort(projects, profitsSize, sizeof(Project), cmp);

    int *maxHeap = (int *)malloc(sizeof(int) * profitsSize);
    int heapSize = 0;

    int projectIndex = 0;
    for (int i = 0; i < k; i++) {
        while (projectIndex < profitsSize && projects[projectIndex].capital <= w) {
            heapPush(maxHeap, &heapSize, projects[projectIndex].profit);
            projectIndex++;
        }

        if (heapSize == 0) {
            break;
        }

        w += heapPop(maxHeap, &heapSize);
    }

    free(projects);
    free(maxHeap);

    return w;
}
11-06 08:40