ctci/16. Moderate problems/16.17. max_subarray.md

104 lines
3.5 KiB
Markdown

# 16.8. Contiguous sequence or Maximum subarray problem
## Given an array of integers, both negative and positive, find the contiguous sequence with the largest sum. Return the sum
> example:
```bash
nums = [2, -8, 3, -2, 4, -10]
output = 5, [3, -2, 4]
```
## First idea
Brute force, check all possible substrings/subarrays and check for the maximum. Keep track of the biggest, discard those smaller. Very bad complexity.
```bash
1. [2]:2
2. start with [2,-8]: -6
3. [2, -8, 3]: -3. but [-8, 3]: -5, and [3]: 3
4. [3,-2]: 1
5. [3,-2,4]:5
6. [3,-2,4,-10]:-5
7. [-2,4,-10]:-8
8. [-4,-10]:-6
```
This is O(n), but does it work for each case?
```bash
nums = [2, -12, 3, -5, 4, -10]
possibility = max(nums) = 4
output = 4
1. [2]:2
2. [2,-12]:-10
3. [3,-5]:-2
4. [4, -10]:-6
```
if max(nums) > 0, find first positive element in array. Negative values with abs(neg) > max(nums) are useless. We might have [3,-1,4,-1,2]:7 and this might win.
```bash
nums = [2, 1, 1, 1, -8, 3, -1, 4, -2, 3, -1, -1, -1, -3, -6]
possibility = max(nums) = 4
output = 7
1. [2]:2
2. [2,1,1,1]:5 (until negative num. if neg > 4, discard).
3. [3,-1,4-2,3]:7 iterate through the array, if the sequence > max, keep track of highest and index. when we go lower, keep track until sum of sequence < max
4. [3,-1,4-2,3,-1,-1,-1]:4 Can we break? before finishing the array? but what if there is a huge sequence of max-1 max-1 max-1 max-1... we can only break this sequence if total sum < 0
```
Another possibility
```bash
nums = [3, -1, 4, -2, 3, -1, -1, 3, -3, -6]
possibility = max(nums) = 4
output = 8, [3, -1, 4, -2, 3, -1, -1, 3]
```
But what if:
```bash
nums = [3, -1, 4, -2, 3, -1, -3, 3, -6, 4]
possibility = max(nums) = 4
output = 7, [3, -1, 4, -2, 3]
```
We still have to consider the whole subarray as long as the sum is positive, because if we find a max value, it will boost the sum.
```bash
nums = [4, -3, 3, -4, 4, -1, 1, 3, -7]
possibility = max(nums) = 4
output = 7, [4, -3, 3, -4, 4, -1, 1, 3]
```
Have to consider the whole substring until total value is negative.
```bash
nums = [4, -3, 3, -4, 4, -1, 1, 3, -7, 2, 2, 4]
possibility = max(nums) = 4
output = 8 [2, 2, 4]
```
If max value is negative, the threshold of keeping the subarray is until total sum is smaller than 2*max. but no, if maxval is negative, all the other numbers in the array will also be negative, so sum decreseases. return max(nums).
Tests passed, code works! O(n), O(1) space. Is this greedy algorithm?
## Hints
* A sequence of values with negative sum never start or end a sequence, they might be in the middle of a longer sequence.
* Start from the beginning of the array. As that subsequence gets larger, it stays as the best subsequence. Once it becomes negative, it's useless.
* When the sum is negative, reset the count
* This can be solved in O(n) time and O(1) space.
I think I got it right.
## Solution
We only want negative numbers inculded in the sequence when they are in the middle of two positive sequences, each of which have a sum greater than the negative value. When the maxval is surpassed, we keep track of the new maxval and sum/count. Keep updating the sum until either maxval is surpassed again, or sum is negative. if that's the case, reset sum.
My code is exactly the same as the solution! (except for some unecessary variables I had).
If all numbers in the array are negative, can we consider a subsequence of length = 0 and thus maxval = 0? or does it need to have 1+ values? this is a good thing to consider with the interviewer.