next greater element in array - c++

#include<iostream>
#include <stack>
using namespace std;
void printNextGreaterElement(int input[], int inputSize) {
stack<int> s;
s.push(input[0]);
for (int i = 1; i < inputSize; i++) {
while (!s.empty() && s.top() < input[i]) {
cout<<"Next greater element for "<<s.top()<<"\t = "<<input[i]<<"\n";
s.pop();
}
s.push(input[i]);
}
while (!s.empty()) {
int top = (int) s.top();
s.pop();
cout<<"Next greater element for "<<top<<"\t = null\n";
}
}
int main() {
int input[] = { 98, 23, 54, 12, 20, 7, 27 };
printNextGreaterElement(input, 7);
return 0;
}
I was learning about NGE in the array and came across this piece of code which I found on geeksforgeeks and other websites, but isn't this gives wrong output for the test case:
14
10 3 12 4 2 9 13 0 8 11 1 7 5 6

Given an array, print the Next Greater Element (NGE) for every element. The Next greater Element for an element x is the first greater element on the right side of x in array.
Your code seems to be fine and gives the correct output of the input which you told gives wrong output is as following.
The input is as you mentioned
14
10 3 12 4 2 9 13 0 8 11 1 7 5 6
The output is
Next greater element for 3 = 12
Next greater element for 10 = 12
Next greater element for 2 = 9
Next greater element for 4 = 9
Next greater element for 9 = 13
Next greater element for 12 = 13
Next greater element for 0 = 8
Next greater element for 8 = 11
Next greater element for 1 = 7
Next greater element for 5 = 6
Next greater element for 6 = null
Next greater element for 7 = null
Next greater element for 11 = null
Next greater element for 13 = null
For example, the second element in the array is 3, the next greater element in the array is 12 (Which is the output).
The explanation of the algorithm is not given here as it is well written in the post you mentioned.

Related

Recursive function to check all pairs in an array

an int vector is given, and I need to find the maximum sum of number sequences that are more than 3 positions away from each other. So an example:
Input: 10, 5, 6, 7, 16, 18, 12
Output: 29
Explanation:
candidate "routes":
10-7-12 = 29
10-16 = 26
10-18 = 28
5-16 = 21
5-18 = 23
5-12 = 17
...
16
18
12
I want to solve this problem using recursion and I have gotten to the point where the program tests all paths with numbers that are more than 3 positions away. However, it fails to test all the paths starting from the same digit.
Here my code:
#include <iostream>
using namespace std;
const int n = 7;
int sum = 0;
int temp=0;
void rec(int (*arr), int ind){
if (ind > n-3){
if(temp > sum)
sum = temp;
temp=0;
return;
}
temp += arr[ind];
cout<<arr[ind]<<" ";
for(int i=3;i<n;i++)
rec(arr, ind+i);
cout<<endl;
}
int main(){
int arr[n] = {10, 9, 9, 9, 8, 8, 7};
for(int i=0;i<n;i++)
rec(arr, i);
cout<<endl<<endl<<"Max: "<<sum;
return 0;}
Output:
10 9 7
8
8
7
9 8
8
7
9 8
7
9 7
8
8
7
Max: 26
Even though in this case the output is correct, you can see that it tests only 10-9-7 and not the other 10-8, 10-8 and 10-7. It seems it doesn´t even go in the first for-loop I called the function recursively.
Am I understanding something wrong or how do I accomplish that it tests all pairs that are more than 3 positions away?
There are 3 problems here:
Based on your output:
10 9 7
8
8
⋮
Your code actually loops through all the possible routes. Instead of thinking your second line 8 and third line 8 as two complete routes, they were actually derived from your first rout 10 9 7. So really think of it like this:
10 --- 9 --- 7
`- 8
`- 8
`- 7
9 --- 8
`- 8
`- 7
⋮
That's actually not your output. Plugged your code in, I got my output:
10 9
8
9 8
9
9
8
Max: 19
The reason that it didn't go through all routes is because your line:
if (ind > n-3)
{
⋮
return;
}
You are terminating your loop way too early. Instead, you should only end it right before it goes out of index. So it should be:
if (ind > n - 1)
{
⋮
}
Your logic actually has flaws.
Because you always set your temp back to 0 once reached the last possible number inside the array, you actually lost some part of your previous sums. You can easily create a sequence that makes it fails, such as: 10, 9, 9, 7, 8, 20, 7.
Instead of having temp as a global, it would be better to set it local, and being passed to each recursions.
To do that, you would need to add the temp as a parameter of your rec function, and call it like:
void rec(int (*arr), int ind, int temp)
{
⋮
rec(arr, i, temp);
⋮
}
int main()
{
⋮
rec(arr, i, 0);
⋮
}
Or if you want to keep the signature the same in your main, you could also add a default argument in your rec:
void rec(int (*arr), int ind, int temp = 0)
Side note, I would considering using std::array or std::vector instead of c-style array, to avoid having a global size n or passing int (*arr) in your function. Plus you can easily make your arr as a longer sequence.

Segmentation Fault when popping from a stack

Anyone can help me with finding out the error with this code? This is for a hackerrank question MAXIMUM ELEMENT. For the case 2, the line "maxes.pop()" keeps giving me segmentation fault. Commenting that line out actually allows the code to compile.
QUESTION:
You have an empty sequence, and you will be given queries. Each query is one of these three types:
1 x -Push the element x into the stack.
2 -Delete the element present at the top of the stack.
3 -Print the maximum element in the stack.
Function Description
Complete the getMax function in the editor below.
getMax has the following parameters:
string operations[n]: operations as strings
Returns
int[]: the answers to each type 3 query
Input Format
The first line of input contains an integer, . The next lines each contain an above mentioned query.
Constraints
Constraints
All queries are valid.
Sample Input
STDIN Function
----- --------
10 operations[] size n = 10
1 97 operations = ['1 97', '2', '1 20', ....]
2
1 20
2
1 26
1 20
2
3
1 91
3
Sample Output
26
91
vector<int> getMax(vector<string> operations) {
stack<int> nums;
stack<int> maxes;
vector<int> maxnums;
int max = INT_MIN;
//int top = -1;
for(long unsigned int i=0; i<operations.size(); i++){
switch(operations[i][0]){
case('1'):
cout<<"Operation 1"<<endl;
nums.push(stoi(operations[i].substr(2)));
if(nums.top() > max){
max = nums.top();
maxes.push(max);
}
break;
case('2'):
cout<<"Operation 2"<<endl;
if(max==nums.top()){
//cout<<"top element in maxes"<<maxes.top()<<endl;
maxes.pop();
max = maxes.top();
}
nums.pop();
break;
case('3'):
cout<<"Operation 3"<<endl;
maxnums.push_back(maxes.top());
break;
}
}
return maxnums;
}
Consider the following input sequence:
1 1 // push 1. Pushes 1 into nums and maxes
1 1 // push 1. Pushes 1 into nums, but not into maxes, since max = 1.
3 // delete top stack element
3 // delete top stack element
Before processing the first 3 line, your state will be this:
nums = {1, 1}
maxes = {1}
max = 1
Now, on the first pop, everything will be fine, so after the first pop, you will end up with this state:
nums = {1}
maxes = {}
max = 1
However, on on the second pop, max == nums.top() is still true, so you pop from your maxes stack, which is already empty. That is why it gives you the segmentation fault.

How to construct a tree given its depth and postorder traversal, then print its preorder traversal

I need to construct a tree given its depth and postorder traversal, and then I need to generate the corresponding preorder traversal. Example:
Depth: 2 1 3 3 3 2 2 1 1 0
Postorder: 5 2 8 9 10 6 7 3 4 1
Preorder(output): 1 2 5 3 6 8 9 10 7 4
I've defined two arrays that contain the postorder sequence and depth. After that, I couldn't come up with an algorithm to solve it.
Here's my code:
int postorder[1000];
int depth[1000];
string postorder_nums;
getline(cin, postorder_nums);
istringstream token1(postorder_nums);
string tokenString1;
int idx1 = 0;
while (token1 >> tokenString1) {
postorder[idx1] = stoi(tokenString1);
idx1++;
}
string depth_nums;
getline(cin, depth_nums);
istringstream token2(depth_nums);
string tokenString2;
int idx2 = 0;
while (token2 >> tokenString2) {
depth[idx2] = stoi(tokenString2);
idx2++;
}
Tree tree(1);
You can do this actually without constructing a tree.
First note that if you reverse the postorder sequence, you get a kind of preorder sequence, but with the children visited in opposite order. So we'll use this fact and iterate over the given arrays from back to front, and we will also store values in the output from back to front. This way at least the order of siblings will come out right.
The first value we get from the input will thus always be the root value. Obviously we cannot store this value at the end of the output array, as it really should come first. But we will put this value on a stack until all other values have been processed. The same will happen for any value that is followed by a "deeper" value (again: we are processing the input in reversed order). But as soon as we find a value that is not deeper, we flush a part of the stack into the output array (also filling it up from back to front).
When all values have been processed, we just need to flush the remaining values from the stack into the output array.
Now, we can optimise our space usage here: as we fill the output array from the back, we have free space at its front to use as the stack space for this algorithm. This has as nice consequence that when we arrive at the end we don't need to flush the stack anymore, because it is already there in the output, with every value where it should be.
Here is the code for this algorithm where I did not include the input collection, which apparently you already have working:
// Input example
int depth[] = {2, 1, 3, 3, 3, 2, 2, 1, 1, 0};
int postorder[] = {5, 2, 8, 9, 10, 6, 7, 3, 4, 1};
// Number of values in the input
int n = sizeof(depth)/sizeof(int);
int preorder[n]; // This will contain the ouput
int j = n; // index where last value was stored in preorder
int stackSize = 0; // how many entries are used as stack in preorder
for (int i = n - 1; i >= 0; i--) {
while (depth[i] < stackSize) {
preorder[--j] = preorder[--stackSize]; // flush it
}
preorder[stackSize++] = postorder[i]; // stack it
}
// Output the result:
for (int i = 0; i < n; i++) {
std::cout << preorder[i] << " ";
}
std::cout << "\n";
This algorithm has an auxiliary space complexity of O(1) -- so not counting the memory needed for the input and the output -- and has a time complexity of O(n).
I won't give you the code, but some hints how to solve the problem.
First, for postorder graph processing you first visit the children, then print (process) the value of the node. So, the tree or subtree parent is the last thing that is processed in its (sub)tree. I replace 10 with 0 for better indentation:
2 1 3 3 3 2 2 1 1 0
--------------------
5 2 8 9 0 6 7 3 4 1
As explained above, node of depth 0, or the root, is the last one. Let's lower all other nodes 1 level down:
2 1 3 3 3 2 2 1 1 0
-------------------
1
5 2 8 9 0 6 7 3 4
Now identify all nodes of depth 1, and lower all that is not of depth 0 or 1:
2 1 3 3 3 2 2 1 1 0
-------------------
1
2 3 4
5 8 9 0 6 7
As you can see, (5,2) is in a subtree, (8,9,10,6,7,3) in another subtree, (4) is a single-node subtree. In other words, all that is to the left of 2 is its subtree, all to the right of 2 and to the left of 3 is in the subtree of 3, all between 3 and 4 is in the subtree of 4 (here: empty).
Now lets deal with depth 3 in a similar way:
2 1 3 3 3 2 2 1 1 0
-------------------
1
2 3 4
5 6 7
8 9 0
2 is the parent for 2;
6 is the parent for 8, 8, 10;
3 is ahe parent for 6,7;
or very explicitly:
2 1 3 3 3 2 2 1 1 0
-------------------
1
/ / /
2 3 4
/ / /
5 6 7
/ / /
8 9 0
This is how you can construct a tree from the data you have.
EDIT
Clearly, this problem can be solved easily by recursion. In each step you find the lowest depth, print the node, and call the same function recursively for each of its subtrees as its argument, where the subtree is defined by looking for current_depth + 1. If the depth is passed as another argument, it can save the necessity of computing the lowest depth.

How to recount a process after a certain number in a vector

Let's assume I have an array of years.
int year[20];
The plan is to make an if condition and work with a segment of the months in the year vector.
The segment I want to work with is from September to February. Therefore the range of year I always want to pick is (year >=9 && year <3)
Therefore I have two vectors. One is for the year, and another one is for that I count to count the entry.
For example:
vector <int> year{1,2,3,5,10,2,10,12,11,12,2,2,3,5,8,2,8,12,8,12};
vector <int> list{1,2,3,2,1,1,2,3,2,1,5,3,2,5,6,5,3,2,5,6};
the size of both the above vectors is 20. What I want to do is to count the vector entry from list in each year segment I'm looking into.
If we look at both vectors above, the first month segment in year vector would be:
from year[0] =1 to year[1] =2. and the count is 2.
The next segment would be: from year[4] =10 to year[5] =2. So the print out entries would be from the vector list: list[4]=1, and list[5] =1. and the total count is 2.
After the segment work is done I want to reassign the count to zero to start it again and iterate through out the whole vector of year.
Here is the some work I did. My problem is that, I can make the segment in the if statement, but I'm trying to assign the count =0 each time each year segment is complete.
#include <iostream>
#include <string>
#include <cstdlib>
#include <vector>
using namespace std;
int main()
{
unsigned int count =0;
vector <int> year{1,2,3,5,10,2,10,12,11,12,2,2,3,5,8,2,8,12,8,12};
vector <int> list;
for (int x =0; x<20; x++)
{
//cout << "random number" << (1+ rand()%12)<< endl;
list.push_back((1+ rand()%4));
}
for (int j=0; j<=20; j++)
{
if (year[j] >=9 && year[j]<3)
{
count++;
cout <<list[j]<< "counting the entry of each segment"<< count<<endl;
}
}
}
The way I want to select the segment if the entries in the vector year for example, 1= January, 2 = February satisfies the September to February conditions. So each segment would be greater or equal to 9 and less than 3.
As I increment to the vector year, I find a segment that satisfies the condition and goes to the next segment that satisfies the condition again.
Each time I' done with the operation in if condition with each segment, I want to assign the count =0, so I can recount how many entries in the next segment.
Since the month goes like in ascending order, from the example {11, 10}
will count as 1 with two segments instead of two. The segments will be {11}, and {10}, instead of {11, 10} where it counts the elements entry =2.
I propose to look at (year[j]+9)%12 instead of directly at year[j].
Everything >= 6 is in your range (6,7,8,9,10,11) , i.e. the unwanted other 6 months (0,1,2,3,4,5) are outside. That also makes detecting the start of a new segment much easier.
year[j] (year[j]+9)%12 wanted
1 10 x
2 11 x
3 0
4 1
5 2
6 3
7 4
8 5
9 6 x
10 7 x
11 8 x
12 9 x
The values in your vector become:
wanted reset
1 10 x
2 11 x
3 0 r
5 2
10 7 x
2 11 x
10 7 x r
12 9 x
11 8 x r
12 9 x
2 11 x
2 11 x
3 0 r
5 2
8 5
2 10 x
8 5 r
12 9 x
8 5 r
12 9 x
This shows where you want to reset the count and start working on a new segment, which is whenever (year[j]+9)%12 is not greater than at previous index.
The formula (year[j]+9)%12 works by shifting the "virtual month" you are looking at, by using the +9 part and making sure that the result still is in the 0-11 range for twelve months, by the %12 part. I.e. that "1" (seen as "10") is seen higher than "12" (seen as "9"). So that going from 12 (9) to 1 (10) does not trigger the reset, but going from 2 (11) to 3 (0) does trigger the reset, because the segment obviously ended. Also going from , 2 (11) to 10 (7), triggers the reset; which is needed, because (3-8) occur in between and hence a new segment needs to be started, even though 10 is higher than 2.

Why does my multidimensional vector only push_back 0 index?

I having a problem using push_back(), I can't figure out why only the first cols vector is just pushed over and over again.
Input
10 9 10 3 100 8 7 10 73 9 10 5 9 87 -1 8 3 7 10 92 6 10 6 83 9 11 8 8 77 -1 10 10 10 10 100 10 10 10 100 10 10 10 10 100 -1 DONE
C++
(...)
size = numbers.size();
counter = 0;
square = ceil(sqrt(size));
vector < vector <int> > rows;
vector<int> cols;
do {
for (int i = 0; i < square; ++i) {
cols.push_back(numbers[counter]);
cout << cols[i] << " ";
++counter;
}
rows.push_back(cols);
cout << endl;
} while (counter <= size);
(...)
Undesirable Output
0: 10 9 10 3 100 8 7
1: 10 9 10 3 100 8 7
2: 10 9 10 3 100 8 7
3: 10 9 10 3 100 8 7
4: 10 9 10 3 100 8 7
5: 10 9 10 3 100 8 7
6: 10 9 10 3 100 8 7
rows[1][2] should be 73, not 9. Where have I gone wrong?
You never reset cols. Instead you just keep adding on to it. I think you are printing rows out with magic number indices, which is why you do not spot the added portion. Either declare a temporary cols inside the loop or call clear after each push_back().
awesomeyi found your main problem. But your code has other issues too.
There is a buffer overflow. For example if size == 4 then square == 2
and we get:
after iter #1: counter == 2; continue since 2 <= 4
after iter #2: counter == 4; continue since 4 <= 4
iter #3: reads numbers[4] and numbers[5] - oops!
The loop condition should be:
while (counter + square <= size);
we need to make sure that the next iteration will complete without overflowing the vector. It would be smart to use .at() for vector access so that if you did make a miscalculation, then the error will behave nicely instead of going screwball.
The loop (minus the output) could actually be written as:
for (size_t counter = 0; counter + square <= size; counter += square )
{
std::vector<int> cols( numbers.begin() + counter, numbers.begin() + counter + square );
rows.push_back(cols);
}