105 lines
3.5 KiB
Markdown
105 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.
|