Maximum subarray_problem understanding [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am researching the maximum subarray problem. It would appear that I haven't gotten the core idea. Let's say you have the following array: int arr[] ={10, 4, 2, 12, 16, 1} From what I understand the maximum subarray should be equal to 14, since the lowest and highest possible sub array is 2 (the third element) and 16 (the 5th element) right? Well, apperantly not. I implemented the linear time algorithm which I found here: http://heliang.me/wiki/index.php?title=4.1_The_maximum-subarray_problem
It's implementation in c++"
int max_sarr(int arr[], int size)
{
int max_sum = -9999;
int sum = 0;
for(int i = 0; i < size; i++)
{
sum += arr[i];
if(sum > max_sum)
max_sum = sum;
if(sum < 0)
sum = 0;
}
return sum;
}
int main()
{
int arr[] = {10, 4, 2, 12, 16, 1};
int p = max_sarr(arr, 6);
cout << p << endl;
return 0;
}
The output is 45. So... where is the mistake in my thought process ?

You misunderstand the problem. The problem is to find the contiguous subarray of the given array such that it has the highest sum of all subarrays. That is, it basically finds a first element and last element within the array which, if you summed up the elements including and between them, would give you the maximum possible value.
If all of the values in your array are positive, then the maximum subarray is always the entire array. In this case, if you add up all the elements in the array, you get 45.
Consider an array with values {-5, 10, -3, 22}. We can enumerate all of the subarrays of this:
Subarrays of length 0: {}
Subarrays of length 1: {-5} {10} {-3} {22}
Subarrays of length 2: {-5, 10} {10, -3} {-3, 22}
Subarrays of length 3: {-5, 10, -3} {10, -3, 22}
Subarrays of length 4: {-5, 10, -3, 22}
The subarray with the maximum sum is {10 -3 22}, whose sum is 29.

sftrabbit's answer is great, however I strongly recommend the The Maximum Subarray Problem section in CLRS book page 68. It is very clear and it also discusses the asymptotic complexity and the real life occurences of the problem.
In addition to this, as you might expect, an array with all positive elements, the maximum subarray of it will be the array itself.

Related

Find the first element that is n times larger than current element in a list

It is easy to come up with an O(n) algorithm to solve this very famous question:
For every element in the list, find the first element that is larger than it. This can be done using a stack. But, what if I want to find the first element that is larger than n*current element?
More specifically:
Given an array [2, 5, 4, 7, 3, 8, 9, 6] and n = 2.
I want [5, -1, 9, -1, 8, -1, -1, -1]
For 2, 5 is the next element larger than n * 2, for 4, 9 is the next element larger than n * 4. For 5, there is no element larger than n * 5 so return -1 at that position.
Can we do better than O(n^2)?
I agree with OP that, the simple predicate of the O(N) algo might not work on the stack-based solution when looking for the first element > 2x in the remaining array.
I found a O(NlogN) solution for this btw.
It uses a Min-heap to maintain the frontier elements we are interested in.
Pseudo-code:
def get_2x_elements(input_list, multipler = 2):
H = [] #min-heap with node-values as tuples (index, value)
R = [-1 for _ in range(len(input_list))] # results-list
for index, value in enumerate(input_list):
while multiplier*H[0][1] < value:
minval = extractMinFromHeap(H)
R[minval[0]] = value
insertToMinHeap(H, (index, value))
return R
Complexity-analysis:
1. Insertion/Extraction from min-heap = O(logN)
2. Number of such operations = N
Total-complexity = O(NlogN)
PS: This assumes we need the first >2x element from the remaining part of the list.
Re:
I made a Java verion implementation of your idea. Thanks #Serial Lazer
private static class ValueAndIndexPair implements Comparable<ValueAndIndexPair>{
public final double value;
public final int index;
public ValueAndIndexPair(double value, int index) {
this.value = value;
this.index = index;
}
#Override
public int compareTo(ValueAndIndexPair other) {
return Double.compare(value, other.value);
}
}
public static double[] returnNextNTimeLargerElementIndex(final List<Double> valueList, double multiplier) {
double[] result = new double[valueList.size()];
PriorityQueue<ValueAndIndexPair> minHeap = new PriorityQueue<>();
// Initialize O(n)
for (int i = 0; i < valueList.size(); i++) {
result[i] = -1.0;
}
if (valueList.size() <= 1) return result;
minHeap.add(new ValueAndIndexPair(valueList.get(0) * multiplier, 0));
for (int i = 1; i <valueList.size(); i++) {
double currentElement = valueList.get(i);
while (!minHeap.isEmpty() && minHeap.peek().value < currentElement) {
result[minHeap.poll().index] = currentElement;
}
minHeap.add(new ValueAndIndexPair(currentElement * multiplier, i));
}
return result;
}
Sure, easily.
We just need a sorted version of the array (sorted elements plus their original index) and then we can do an efficient search (a modified binary search) that points us to the start of the elements that are larger than the current number (or a multiple of it, it doesn't matter). Those elements we can then search sequentially for the one with the smallest index (that is greater than the one of the current number, if so required).
Edit: It was pointed out that the algorithm may not be better than O(n²) because of the sequential search of the elements that satisfy the condition of being greater. This may be so, I'm not sure.
But note that we may build a more complex search structure that involves the index already, somehow. This is left as homework. :)
The stack-based solution offered at geeksforgeeks does not seem to maintain the order of the elements in the result even in its output:
input: int arr[] = { 11, 13, 21, 3 };
output:
11 -- 13
13 -- 21
3 -- -1
21 -- -1
After minor modification to find the first element which is greater N times than a current, this algorithm fails to detect 9 for the element 4 from the given example.
Online demo
input: int arr[] = { 2, 5, 4, 7, 3, 8, 9, 6 }; // as in this question
output:
2 * 2 --> 5
2 * 3 --> 8
6 -- -1
9 -- -1
8 -- -1
7 -- -1
4 -- -1
5 -- -1
Thus, initial assumption about existing solution with complexity O(N) is not quite applicable to the expected result.

What is the mistake in my code for the problem "Find Median from Data Stream"? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I'm been struggling to solve the question Find Median from Data Stream on LeetCode for the last 2 hours but couldn't find the mistake in my code.
My algorithm is to put two priority queues, the first one is a max-priority queue which stores the elements less than the median, and the second one is a min-priority queue which stores the elements greater than the median.
This is my code:
struct get_min{
bool operator()(int i, int j){
return i>j;
}
};
class MedianFinder {
//queue which stores elements which are greater than the median
priority_queue<int, vector<int>, get_min> max;
int minSize, maxSize;
//queue which stores elements which are less than the median
priority_queue<int> min;
public:
MedianFinder() {
minSize = 0;
maxSize = 0;
}
void addNum(int num) {
if(minSize>maxSize){
int x = min.top();
if(x<num){
max.push(num);
}else{
min.push(num);
max.push(min.top());
min.pop();
}
maxSize++;
}else if(minSize < maxSize){
int x = max.top();
if(x>num)min.push(x);
else{
max.push(num);
min.push(max.top());
max.pop();
}
minSize++;
}else if(minSize==0 && maxSize==0){
min.push(num);
minSize++;
}else{
int x = min.top();
int y = max.top();
if(num<=x){
min.push(num);
minSize++;
}else{
max.push(num);
maxSize++;
}
}
}
double findMedian() {
if(minSize> maxSize)return min.top();
else if(minSize<maxSize)return max.top();
else return (double(min.top()+max.top())/2);
}
};
For the input where the following numbers are given one by one and the median of those numbers should be output after taking each number as input, I'm getting the incorrect output.
Stream of numbers:
6, 10, 2, 6, 5, 0, 6, 3, 1, 0, 0
My output:
6, 8, 6, 6, 6,5.5, 6, 6, 6,5.5, 5
Expected Output:
6, 8, 6, 6, 6,5.5, 6,5.5, 5, 4, 3
As Jerry Jeremiah commented the issue with the code,
in the line, if(x>num)min.push(x); you are completely ignoring the num and pushing x into the queue. You have to change that and your code will get accepted.

sum values in a range of indices with O(1) complexity [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
We are given a integer vector(V[]) and two index values, A and B. We need to sum all the integers between V[A] and V[B].
For example,
V[] == {0, 1, 2, 0, 4, 0, 3}, A == 2, B == 6
Sum == V[3] + V[4] + V[5] == 4
Is it possible to solve with O(1) complexity?
I thought about using memory address operations, but I'm still not sure how it would work(something like: sum the next (B-A) addresses values from &V[A])
If preprocessing is allowed, this can be done with a secondary array.
Each element of the second array would contain the sum of the corresponding element and all preceeding elements. This one-time preprocessing is O(n) time and O(n) space.
For example:
int Vsum[7];
Vsum[0] = V[0];
for (int i=1; i<7; i++) {
Vsum[i] = Vsum[i-1] + V[i];
}
So with your given array, the corresponding summation array Vsum would contain:
{0, 1, 3, 3, 7, 7, 10}
Once you have this, you only need to perform 2 lookups: one for the upper bound and one for the lower bound. So after preprocessing, getting the range sum is O(1) every time it is performed.
For the example of A==2 and B==6, you would then calculate Vsum[B-1] - Vsum[A] == 7 - 3 == 4
O(1) Space: no problem. But O(n) time will always be required for "random" numbers.

Maximum contiguous sub-array (With most number of elements)

Given an array of natural numbers and an another natural T, how to find the contiguous subarray with sum less than or equal to T but the number of element in this subarray is maximized?
For example, if the given array is:
{3, 1, 2, 1, 1} and T = 5. Then the maximum contigous subarray is {1, 2, 1, 1} because it will contain 5 elements and the sum is equal to 5.
Another example: {10,1,1,1,1,3,6,7} with T = 8. Then the maximum contigous subarray is ${1,1,1,1,3}$
I can do it with O(n^2) operation. However I am looking for a linear time solution for this problem. Any ideas?
It ought to be possible to do this with O(n). I've not tested this, but it looks OK:
int start = 0, end = 0;
int beststart = 0, bestend = 0;
int sum = array[0];
while (end + 1 < arraysize) {
if (array[end + 1] + sum <= T)
sum += array[end++];
else
sum -= array[start++];
if ((end - start) > (bestend - beststart)) {
beststart = start;
bestend = end;
}
}
So, basically, it moves a sliding window along the array and records the point at which end - start is the greatest.
It seems to be a capped version of the Maximum subarray problem: http://en.wikipedia.org/wiki/Maximum_subarray_problem
I guess you can find inspirations with existing algorithms.

Making a long vector(coloumn Matrix) using small arrays [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I'm trying to make one vector(feature vector) which contains array elements.
Suppose I have an array arr1 of size nx1 in first iteration. I have to add this array elements to the CvMat matrix featureVect of size, 2*n x 1.
In next iteration I have an array arr2 of size nx1, and now I have to add this array to featureVect from row n+1 to 2*n (using a one-based index)
Suppose I have
int arr1[4] = {1, 2, 3, 4};
int arr2[4] = {5, 6, 7, 8};
CvMat *featureVect;
Now I want the result to look like this (where featureVect is a one column matrix)
featureVect = {1, 2, 3, 4, 5, 6, 7, 8};// featureVect size is 8x1;
If you're using C++ with OpenCV I would recommend the Mat class. Then,
Mat featureVect(8,1,CV_32S); //CV_32s <=> int (32-bit signed integer)
const int n = 4;
for(int i = 0; i < n; ++i)
{
featureVect.at<int>(i,0) = arr1[i];
featureVect.at<int>(i+n,0) = arr2[i];
}