My friend got asked a question in an interview:
Given an array, say: [4, 6, -10, -1, 10, -20] and a value k, say: 4, you have to return the maximum sum of k elements from the array such that every time you select an element, you need to discard either all elements to its left or those to its right. For e.g., if you select -10, you have to discard either [4,6] or [-1, 10, -20]. For the given e.g., output should be 19 (4 + 6+ -1 + 10).
Note that: number of array elements n <= 10^5; and k<=n.
The way I thought about this problem is to do a two way pass over the array (left to right and then vice versa). While doing a pass, we use a sliding window (multiset) of size k
(popping least elements from it if size > k) and keeping track of the maximum sum of the window elements as we slide. Then we reverse the array and repeat the same logic on the reversed array and then return the final max sum:
#include<bits/stdc++.h>
using namespace std;
long helper(vector<int>&nums, int k) {
multiset<long> st;
long sum=0l, res=LONG_MIN;
for(int j=0; j<nums.size(); j++) {
sum+=nums[j];
st.insert(nums[j]);
if(j<k-1) continue;
while(st.size()>k) {
sum-=*st.begin();
st.erase(st.begin());
}
res=max(res, sum);
}
return res;
}
long solution(vector<int>&nums, int k){
long res1=helper(nums, k);
reverse(begin(nums), end(nums));
long res2=helper(nums, k);
return max(res1, res2);
}
int main() {
vector<int> nums={-5,4,-10,-1,-5,8,-3};
cout<<solution(nums, 3)<<endl;
nums={4,4,4,4,4};
cout<<solution(nums, 4)<<endl;
return 0;
}
I tried it on a few examples and it returns the correct expected responses (ideone.com link). Is my approach correct? Thanks!
Explanation:
a. For [4, 6, -10, -1, 10, -20]
, we first select 10 (and discard -20 to the rigth).
b. Next we select 4
and discard everything to its left (nothing);Now, we have [6, -10, -1]
c. Next we select 6
and discard everything to its left (nothing);Now we have [-10, -1]
d. We finally select -1
.