The problem is as follows:

Given an array $A$ of length $N$, $A[i] \ge 0$ ( $0 \le i \le N-1$) , and a number $K$. Find the longest subarray whose sum is divisible by $K$, if there are no such subarray, return 0;

The idea is to traverse the array and record the result of cumulative sum modulo $K$ and its corresponding index. If for index $i, j$, the remainder is the same, then the subarray between $i, j$ must be a valid subarray (i.e., its sum is divisible by $K$). In order to find the longest subarray, we can keep a list of index corresponding to each remainder (there are $K$ remainders, $0, 1, 2, …, K-1$). During the traversing process, we can also easily find the longest subarray (index list of each remainder is stored in ascending order).

Below is the implementation of the above idea:

int findLongestSubarray(vector<int>& nums){
int N = nums.size();
map<int, vector<int>> indexInfo;

index[0].push_back(-1);

// the remainder at current index
int cur_remainder = 0;
int maxLen = 0;

for (int i = 0; i < N; i++) {
cur_remainder = (cur_remainder + nums[i]) % K;

if (indexInfo[cur_remainder].size() != 0){
maxLen = max(maxLen, i - indexInfo[cur_remainder].front());
}

indexInfo[cur_remainder].push_back(i);
}

return maxLen;
}


Note that the line index[0].push_back(-1); is needed. Otherwise, for $A = [3]$ and $k=3$, we can not the right answer.

Time complexity: traversing the array and finding the maxLen during the process takes $O(n)$ time. Space complexity is apparently $O(n)$.

P.S. Thanks to Scott for pointing out that there is no need to sort the list corresponding to each remainder, because they are already in sorted order.