DOCUSIGN Coding Question – Solved

12 Live
Hackerrank developers want to deploy an application on a set of exactly k servers with different vulnerabilities. They have an option to choose the k servers from a sequence of n servers where vulnerability[i] represents the vulnerability of the ith server. The vulnerability of the chosen k servers is defined as the maximum vulnerability amongst any of the chosen servers. To avoid congestion, they would like to choose a subsequence of k servers such that no two adjacent servers are chosen as part of the k servers. Given an array vulnerability and an integer k, find the minimum possible vulnerability of the chosen servers such that the above condition is respected. Example Given n = 4, k = 2 and vulnerability = [2, 3, 5, 9], only 3 subsequences of k = 2 non-adjacent servers exist: [2, 5] - max = 5 [3, 9] - max = 9 [2, 9] - max = 9 Report 5 as the answer. Function Description Complete the function getMinVulnerability in the editor below. getMinVulnerability has the following parameters: int vulnerability[n]: An array of integers int k: the length of the subsequences to form Returns int: the minimum value returned by the max function for all valid subsequences Constraints 1 <= n <= 10^5 1 <= k <= (n + 1) / 2

Asked in: DOCUSIGN

Image of the Question

Question Image Question Image

All Testcases Passed ✔



Passcode Image

Solution


def getMinVulnerablity(vulnerablity, k):
    def helper(middle_value):
        result = 0
        current = 0
// ... rest of solution available after purchase

🔒 Please login to view the solution

Explanation


```
To solve the problem of selecting a subsequence of exactly k servers from an array of vulnerabilities, such that no two chosen servers are adjacent, and minimizing the maximum vulnerability among the chosen servers, we need a strategy that balances combinatorial selection with optimization constraints. Here’s a detailed thought process and approach framework:

1. **Understanding the Problem:**

We are given:
- An array of vulnerabilities representing servers.
- We want to select exactly k servers from this array.
- The chosen servers must not be adjacent (i.e., if you pick server i, you cannot pick i-1 or i+1).
- Among all valid subsequences that satisfy the above, we want to minimize the maximum vulnerability of the chosen servers.

This is an optimization problem with a combinatorial constraint (no adjacent picks) and an objective function (minimize the maximum vulnerability in the subsequence).

2. **Key Constraints and Observations:**

- Since we must pick exactly k servers, and no two are adjacent, the maximum k allowed is at most (n + 1)/2, because you can't pick more servers than half the array without adjacency.
- Minimizing the maximum vulnerability means you want to keep the chosen servers' vulnerabilities as low as possible, but still satisfy the adjacency and count constraints.
- The adjacency condition heavily restricts which indices can be chosen together, creating a sparse subsequence.
- We want to find the minimum possible "maximum vulnerability" in any valid subsequence of length k.

3. **Potential Approaches to the Problem:**

**A. Brute Force Approach (Impractical):**
- Enumerate all subsequences of length k with no two adjacent servers.
- For each subsequence, compute the max vulnerability.
- Return the minimal maximum.
- This approach is exponentially expensive and infeasible for n up to 10^5.

**B. Greedy or Dynamic Programming:**
- Because of the adjacency restriction, dynamic programming could be used to find the maximum or minimum sum of selected elements.
- But here, the problem is to minimize the maximum element chosen, not sum or count.
- DP solutions would be complex since the "max" function isn't additive, but we could explore if DP can be adapted with binary search or pruning.

**C. Binary Search on the Answer:**
- This is a common technique for problems where you minimize or maximize a value under constraints.
- The idea is to guess a maximum vulnerability threshold M and check if it's possible to pick k servers, non-adjacent, all with vulnerabilities ≤ M.
- If yes, try a smaller M; if no, try a larger M.
- This reduces the problem to a decision problem for a fixed M.

4. **Implementing the Decision Problem (Feasibility Check):**

For a fixed M:
- Construct a boolean array where each position is True if vulnerability[i] ≤ M, False otherwise.
- Now the problem reduces to picking k servers (indices) from the True positions, with no two adjacent indices selected.
- We need to check if it is possible to select k True positions such that no two are adjacent.

5. **Checking Feasibility Efficiently:**

To check if you can pick k servers non-adjacent from positions marked True:
- Iterate through the array.
- Whenever you encounter a True position, you can choose it (increment count), then skip the next position (due to adjacency constraint).
- Continue this greedy selection until you either pick k servers or finish the array.
- If you manage to pick k servers, it means for the current M, the subsequence exists.

6. **Binary Search Range:**

- The minimal possible vulnerability is at least the minimum value in the array.
- The maximum possible vulnerability is the maximum value in the array.
- Perform binary search in this range to find the minimum M for which the feasibility test passes.

7. **Algorithm Summary:**

- Set low = min(vulnerability), high = max(vulnerability).
- While low < high:
- mid = (low + high) // 2
- Check feasibility with threshold mid.
- If feasible, update high = mid.
- Else, update low = mid + 1.
- After the loop, low will hold the minimal maximum vulnerability possible.

8. **Time Complexity and Optimization:**

- Each feasibility check is O(n) since it scans through the array once.
- Binary search performs O(log(max_val - min_val)) iterations.
- Overall complexity is O(n log(max_val - min_val)), which is efficient for the constraints.

9. **Additional Points:**

- Pay attention to edge cases like when k=1 (just pick the smallest vulnerability).
- When all vulnerabilities are the same, answer is that vulnerability.
- Ensure careful handling of the adjacency condition during feasibility.

10. **Why This Approach Works:**

- Binary search on the answer space transforms a complex combinatorial optimization into a series of decision problems.
- The decision problem itself is simple and solvable greedily.
- Combining these techniques results in an efficient and elegant solution.

By thinking along these lines, you move from an intractable brute force idea to a feasible and scalable approach leveraging binary search and greedy feasibility checks to find the minimum possible maximum vulnerability under the constraints given.
```


Related Questions