AMAZON Coding Question – Solved

2 Live
Amazon is launching a revolutionary security feature that incorporates an advanced antivirus program, adept at identifying and halting potential threats. This framework manages n active programs, each with a unique Program Identifier (PID). The antivirus program evaluates the overall security risk of the system using a specialized algorithm. The algorithm analyzes contiguous subarrays of Program Identifiers (PIDs) represented by the array pid. For each subarray, it calculates the sum of the PIDs and divides this sum by a constant k. The remainder obtained from this division is compared to the number of programs in the subarray. A subarray is flagged if the remainder equals the number of programs within it and is considered as malicious. The overall security risk is determined by the total count of such flagged subarrays. Formally, given an array pid of size n, representing the PIDs of the programs running on the computer, and an integer k, with which remainder has to be checked. The task is to calculate the system's security risk level. Remainder is defined as the remaining part after performing the division. For example, the remainder of 13 with 5 is 3. A subarray is a continuous portion of an array. For example, in the array [5, 7, 9, 11] possible subarrays include [5,7], [7, 9, 11], [11] etc. Note that a subarray maintains the original order of elements and consists of consecutive elements. Example: n = 4, pid = [1, 3, 2, 4], k = 4. There are 2 different malicious contiguous subarrays: 1. Subarray from index [0, 0] with pid given by: [1], the remainder of the sum of pid (sum = 1) of the subarray [1] with k = 4 is 1 (the remainder of 1 with 4 is 1), which is equal to the number of elements in the subarray, i.e., 1. Hence, this subarray is flagged. 2. Subarray from index [2, 3] with pid given by: [2, 4], the remainder of the sum of pid (sum = 2 + 4 = 6) of the subarray with k = 4 is 2, which is equal to the number of elements in the subarray, i.e., 2. Hence, this subarray is flagged. An example of a contiguous subarray which is not flagged: - Subarray from index [0, 1] with pid given by: [3, 2] is not flagged because the remainder of the sum of PIDs = 3 + 2 = 5, whose remainder with k = 4, is 1, while there are 2 elements in the subarray. Hence, the subarray is not malicious. Hence, the overall security risk of the system is 2. Thus, return 2 from the function. Function Description: Complete the function findSecurityLevel in the editor below. findSecurityLevel has the following parameters: int pid[n]: an array of integers denoting the PIDs of the programs int k: an integer with which the remainder is checked Returns: long: an integer denoting the overall security risk of the system Constraints: - 1 ≤ n ≤ 2 * 10^5 - 1 ≤ pid[i] ≤ 10^9 - 1 ≤ k ≤ 10^9

Asked in: AMAZON

Image of the Question

Question Image Question Image Question Image

All Testcases Passed ✔



Passcode Image

Solution


from collections import defaultdict
def bruteForce(pid, k):
    n = len(pid)
    answer = 0
// ... rest of solution available after purchase

🔒 Please login to view the solution

Explanation


```
To solve this problem efficiently, you need to first carefully interpret the conditions under which a subarray is considered "malicious." The key idea is that for any contiguous subarray of the PID array, if the sum of its elements modulo k (i.e., the remainder when divided by k) is equal to the number of elements in that subarray, then it is flagged as malicious.

A brute-force approach would be to generate all possible subarrays, compute their sum, take the remainder when divided by k, and then compare it with the length of the subarray. However, given the constraints (up to 200,000 elements), this method would involve O(n^2) or even O(n^3) computations, which is computationally infeasible. Therefore, we need to think about a more efficient way to approach this problem.

Start by observing what it means for a subarray from index i to j (inclusive) to be malicious:
Let’s denote:
- len = j - i + 1, the length of the subarray
- sum(i, j) = prefixSum[j + 1] - prefixSum[i], the sum of elements from index i to j
We want:
(sum(i, j) % k) == len

Now, notice that instead of computing the sum of every subarray from scratch, we can compute a prefix sum array beforehand. The prefix sum array stores the sum of elements up to each index. This allows us to compute the sum of any subarray in constant time.

The crucial insight comes when you try to manipulate the condition algebraically:
(sum(i, j) % k == len) becomes:
((prefixSum[j + 1] - prefixSum[i]) % k == len)

We can rearrange and track this relationship efficiently using modular arithmetic. Here's how:
Let’s define for each prefix sum up to index x: (prefixSum[x] % k) = mod_x

Then, for some earlier index i, if we can find how many times the following holds:
(prefixSum[j + 1] - prefixSum[i]) % k == (j - i + 1)
Then we can count how many such i exist for each j while iterating.

The idea now is to look at all i < j such that:
(prefixSum[j + 1] - prefixSum[i]) % k == (j - i)

Let’s denote current prefix sum modulo as mod_j, and current index as j. We can rearrange the condition to:
(prefixSum[i] % k) == (mod_j - len + k) % k

Here, len = j - i, so you can express this target modulo in terms of j and mod_j.

What this tells you is that as you go through the array, you can keep a map or frequency counter of the prefix mod values you’ve seen so far, but instead of just counting how many times a mod value has occurred, you also track it with the index, to calculate the offset you need.

To make this process efficient, think about how you can reformulate the condition in a way that allows you to use a hash map to track previous prefix sums modulo k, adjusted with index offset. You want to create a mapping between these calculated values and how often they occur, then use that to determine how many valid i values exist for each j as you iterate through the array.

This approach transforms the problem from dealing with every possible subarray (which is far too slow) into a problem of prefix sum modulo management and frequency counting, which can be done in linear time.

In terms of steps:
1. Build a prefix sum as you iterate over the array.
2. For each position, compute the prefix sum modulo k.
3. Use a modified value that includes the offset from the index to match the condition that remainder == length of subarray.
4. Use a hash map to count how many times this modified value has appeared so far.
5. Accumulate the total count of valid matches.

By following this logic, you can reduce what seems to be an O(n^2) problem down to an O(n) solution using prefix sums and a frequency map based on modular arithmetic.

This strategy focuses on transforming the subarray sum and length relationship into a manageable form that allows fast computation. The key lies in understanding how to shift from checking every subarray explicitly to leveraging mathematical patterns and cumulative relationships that allow the use of a hash map for constant-time lookups and updates. This is a common technique in problems involving subarrays with specific properties, and mastering this kind of transformation is essential for efficient algorithm design.
```


Related Questions