Reputation: 11
I'm a frontend dev looking into learning some basic CS fundamentals. I've been doing some leetcode and came across the maximum sub array problem.
https://leetcode.com/problems/maximum-subarray/
I'm try to implement a D/C solution after watching a few videos and came up with the following solution. However, this is not turning out the correct response.
For the following input I am supposed to be returning 6 but I keep returning 4 instead.
Input:
[-2,1,-3,4,-1,2,1,-5,4]
Expected:
6
Actual:
4
Solution:
var maxSubArray = function(nums) {
if (nums.length === 1) {
return nums[0];
}
const mid = Math.ceil(nums.length / 2);
let LSS = maxSubArray(nums.slice(0, mid));
let RSS = maxSubArray(nums.slice(mid));
let leftSum = 0;
let rightSum = 0;
let sum = 0;
nums.slice(0, mid).forEach(num => {
sum += num;
leftSum = Math.max(sum, leftSum);
});
sum = 0;
nums.slice(mid).forEach(num => {
sum += num;
rightSum = Math.max(sum, rightSum);
});
return Math.max(RSS, LSS, (leftSum + rightSum));
};
can someone please explain what I am missing in this solution?
Upvotes: 1
Views: 855
Reputation: 11
use Kadane’s algorithm , in my opinion is best way with O(n) :
var maxSequence = function(arr){
var curr_max = 0, max_so_far = 0;
for(var i = 0; i < arr.length; i++){
curr_max = Math.max(0, curr_max + arr[i]);
max_so_far = Math.max(curr_max, max_so_far);
}
return max_so_far;
}
Upvotes: 1
Reputation: 23955
I believe that since leftSum
in your code is accumulating from the left-bound towards the right, it is not forming a best sum that's contiguous in the middle. The solution offered in Emma's answer correctly iterates outward from the middle both to the left and to the right, therefore finding the best sum that "crosses" the middle as one of our options to consider.
Upvotes: 0
Reputation: 27723
This is a dynamic programming solution, which'll pass:
var maxSubArray = function(nums) {
for (let index = 1; index < nums.length; index++) {
nums[index] = Math.max(nums[index], nums[index] + nums[index - 1]);
}
return Math.max.apply(Math, nums);
};
Or:
var maxSubArray = function(nums) {
for (let index = 1; index < nums.length; index++) {
nums[index] = Math.max(nums[index], nums[index] + nums[index - 1]);
}
return Math.max(...nums);
};
By looking at this Python version, you can see how the algorithm works:
class Solution:
def maxSubArray(self, nums):
for index in range(1, len(nums)):
if nums[index - 1] > 0:
nums[index] += nums[index - 1]
return max(nums)
and here is a LeetCode's divide and conquer solution (similar to your method) based on Java, there was no JavaScript snippet in there:
class Solution {
public int crossSum(int[] nums, int left, int right, int p) {
if (left == right) return nums[left];
int leftSubsum = Integer.MIN_VALUE;
int currSum = 0;
for(int i = p; i > left - 1; --i) {
currSum += nums[i];
leftSubsum = Math.max(leftSubsum, currSum);
}
int rightSubsum = Integer.MIN_VALUE;
currSum = 0;
for(int i = p + 1; i < right + 1; ++i) {
currSum += nums[i];
rightSubsum = Math.max(rightSubsum, currSum);
}
return leftSubsum + rightSubsum;
}
public int helper(int[] nums, int left, int right) {
if (left == right) return nums[left];
int p = (left + right) / 2;
int leftSum = helper(nums, left, p);
int rightSum = helper(nums, p + 1, right);
int crossSum = crossSum(nums, left, right, p);
return Math.max(Math.max(leftSum, rightSum), crossSum);
}
public int maxSubArray(int[] nums) {
return helper(nums, 0, nums.length - 1);
}
}
For additional details, you can see the Discussion Board. There are plenty of accepted solutions with a variety of languages and explanations, efficient algorithms, as well as asymptotic time/space complexity analysis1, 2 in there.
For interviews, we'd like to write bug-free and clean codes based on standards and conventions (e.g., c1, 2, c++1, 2, java1, 2, c#1, 2, python1, javascript1, go1, rust1).
Upvotes: 1