Next Greater Element in the Right using Vector - c++

Problem Statement:
You are given a number n, representing the size of array a.
You are given n numbers, representing elements of array a.
You are required to "next greater element on the right" for all elements of array
Input and output is handled for you.
"Next greater element on the right" of an element x is defined as the
first element to right of x having value greater than x.
Note -> If an element does not have any element on it's right side greater than it,
consider -1 as it's "next greater element on right"
e.g. for the array [2 5 9 3 1 12 6 8 7]
Next greater for 2 is 5
Next greater for 5 is 9
Next greater for 9 is 12
Next greater for 3 is 12
Next greater for 1 is 12
Next greater for 12 is -1
Next greater for 6 is 8
Next greater for 8 is -1
Next greater for 7 is -1
#include <iostream>
#include <stack>
#include <vector>
using namespace std;
void display(vector<int> a){
for(int i=0;i<a.size();i++){
cout<<a[i]<<endl;
}
}
vector<int> solve(vector<int> arr){
vector<int> v;
stack<int> st;
st.push(arr[arr.size()-1]);
v[arr.size()-1] = -1;
for(int i=arr.size()-2;i>=0;i--){
while(!st.empty() && arr[i]>=st.top()){
st.pop();
}
if(st.empty()){
v[i] = -1;
}else{
v[i] = st.top();
}
st.push(arr[i]);
}
return v;
}
int main() {
int n;
cin>>n;
vector<int> arr(n,0);
for(int i=0;i<n;i++){
cin>>arr[i];
}
vector<int> nge(n,0);
nge = solve(arr);
display(nge);
return 0;
}
This is my code and it gives segmentation fault, so need help to know the error in my code.

vector<int> v; is an empty vector, it crashes at v[arr.size()-1] = -1;. When you change it to vector<int> v(arr.size()); it will work, because then the vector has enough elements: https://godbolt.org/z/vcrKe4Ecf
Side notes:
vector<int> a as parameter makes a copy, use const vector<int> &a to avoid the copy.
for(int i=0;i<a.size();i++) will give you a warning, because a.size() returns an unsigned type. The ideal type for i would be size_t, which is the type a.size() returns. Even better would be a range for loop: for (const auto& val: a)

Related

i am getting the wrong output to a problem of finding the equillibrium point in a array

Given an array A of n positive numbers. The task is to find the first Equilibrium Point in an array.
Equilibrium Point in an array is a position such that the sum of elements before it is equal to the sum of elements after it.
Note: Retun the index of Equilibrium point. (1-based index)
this is what i tried
//{ Driver Code Starts
#include <iostream>
using namespace std;
// } Driver Code Ends
class Solution{
public:
// Function to find equilibrium point in the array.
// a: input array
// n: size of array
int equilibriumPoint(long long a[], int n)
// Your code here
int sum=0;
for(int i=1;i<=n;i++)
sum=sum+a[i];
int tempsum=0;
for(int i=n;i>=1;--i)
{
sum=sum-a[i];
tempsum=tempsum+a[i];
if(tempsum==sum+a[i])
return{i};
}
return{-1};
}
};
my output was -1;
You have some syntactic and semantic bugs in your code. For example wongly set braces, wrongly used indices, wrong sequence of statements and so on. Also, your variable names indicate somehow, that you do not understand the underlying algorithm.
And since you have these problems, your function will return -1. This indicates, no value found.
The solution is simple.
You have obviously the "equilibrium Point", which is called "pivot" in normal case, and, as per the requirement, the sum of the values to the left and the sum of the values to the right, shall be the same. So, you have something like a "leftSum" and a "rightSum".
Step 1: In the beginning, for index 0, the right sum is the sum of all values. The left sum is 0
Step 2. For index 1, the right sum, is the previously calculated complete sum minus the value at index 0. The left sum is 0 + value at index 0.
Step 3. For index 2, the right sum, is the previously calculated complete sum minus the value at index 0 minus the value at index 1. The left sum is 0 + value at index 0 + value at index 1.
Step 4. For index 3, the right sum, is the previously calculated complete sum minus the value at index 0 minus the value at index 1 minus the value at index 2. The left sum is 0 + value at index 0 + value at index 1 + value at index 2.
And so on and so on.
Then you just need to compare the left with the right sum. After doing the subtraction and before doing the addition.
The result would be:
#include <iostream>
using namespace std;
class Solution{
public:
// Function to find equilibrium point in the array.
// a: input array
// n: size of array
int equilibriumPoint(long long a[], int n) {
int sum=0;
for(int i=0;i<n;++i)
sum=sum+a[i];
int tempsum=0;
for(int i=0;i<n;++i)
{
sum=sum-a[i];
if(tempsum==sum)
return i+1;
tempsum=tempsum+a[i];
}
return -1;
}
};
int main() {
long long a[]={1,1,5,1,1};
Solution s;
std::cout << s.equilibriumPoint(a, sizeof(a) / sizeof(a[0])) << '\n';
}
With renaming the variables a little bit, you would write:
//{ Driver Code Starts
#include <iostream>
using namespace std;
// } Driver Code Ends
class Solution{
public:
// Function to find equilibrium point in the array.
// a: input array
// n: size of array
int equilibriumPoint(long long a[], int n) {
int rightSum=0;
for(int i=0;i<n;++i)
rightSum=rightSum+a[i];
int leftSum=0;
for(int i=0;i<n;++i)
{
rightSum=rightSum-a[i];
if(leftSum==rightSum)
return i+1;
leftSum=leftSum+a[i];
}
return -1;
}
};
int main() {
long long a[]={1,1,5,1,1};
Solution s;
std::cout << s.equilibriumPoint(a, sizeof(a) / sizeof(a[0])) << '\n';
}

Erasing the first entry of a vector, after the maximum is reached

I have a vector in which i save coordinates.
I perform a series of calculations on each coordinate, thats why i have a limit for the vector size.
Right now i clear the vector, when the limit is reached.
I'm searching for a method, that let's me keep the previous values and only erases the very first value in the vector.
Simplified, something like this (if the maximum size of the vector would be 4).
vector<int> vec;
vec = {1,2,3,4}
vec.push_back(5);
vec = {2,3,4,5}
Is this possible?
As suggested by #paddy, you can use std::deque, it is most performant way to keep N elements if you .push_back(...) new (last) element, and .pop_front() first element.
std::deque gives O(1) complexity for such operations, unlike std::vector which gives O(N) complexity.
Try it online!
#include <deque>
#include <iostream>
int main() {
std::deque<int> d = {1, 2, 3, 4};
for (size_t i = 5; i <= 9; ++i) {
d.push_back(i);
d.pop_front();
// Print
for (auto x: d)
std::cout << x << " ";
std::cout << std::endl;
}
}
Output:
2 3 4 5
3 4 5 6
4 5 6 7
5 6 7 8
6 7 8 9
I think you should properly encapsulate this behaviour in your own vector class, as a std::vector wrapper. You could pass the max capacity as an argument to your constructor. And you could reimplement the methods that may cause "overflow" while just reusing the std::vector ones for the others.
To simplify what you pretend to achieve for the push_back case, using a function and a global variable, you could:
check against a max capacity and,
if that capacity is already reached, rotate your vector contents left by one position; then simply overwrite the last element;
otherwise do a normal push_back.
[Demo]
#include <algorithm> // rotate
#include <iostream> // cout
#include <vector>
const size_t max_capacity{4};
void push_back(std::vector<int>& v, int n)
{
if (v.size() == max_capacity)
{
// Rotate 1 left
std::rotate(std::begin(v), std::begin(v) + 1, std::end(v));
v[v.size() - 1] = n;
}
else
{
v.push_back(n);
}
}
int main()
{
std::vector<int> v{};
for (auto i{1}; i < 9; i++)
{
push_back(v, i);
for (auto&& n : v) { std::cout << n << " "; }
std::cout << "\n";
}
}

print first repeating element using hashmap;

#include <bits/stdc++.h>
using namespace std;
int main() {
unordered_map<int,int>h;
int T;
int n,i;
cin>>T;
while(T--)
{ int flag=0;
cin>>n;
int arr[n];
for( i=0;i<n;i++)
{
cin>>arr[i];
}
for(i=0;i<n;i++)
{
h[i]=count(arr,arr+n,arr[i]);
}
for(auto x: h)
{
if(x.second>1)
{ flag=1;
cout<<x.first<<endl;
break;
}
}
if(flag==0)
{ cout<<-1<<endl;
}
}
}
Given an integer array. The task is to find the first repeating element in the array i.e., an element that occurs more than once and whose index of first occurrence is smallest.
I am getting infinite result. what am I don't wrong. the test cases are below
Input:
test case :1
array size:7
array(1 5 3 4 2 4 5 )
Output:
2
Since you're using an std::unordered_map, the approach should be very simple:
Set the minimum position to a large value.
Loop on the number data from first item to last.
If the number does not exist in the map, then
Add the item and position to the map
else
Set the minimum position to min(minimum position, position found in map)
There is no need for flag variables (which will almost always cause issues somewhere, and most likely the reason for your error), or a recount over and over again of the items in the original array like this:
for(i=0;i<n;i++)
{
h[i]=count(arr,arr+n,arr[i]);
}
If you had 1000 numbers, you would be calling this count loop 1000 times. That is very inefficient.
As to your implementation, where do you store the index of the first duplicate? I don't see it, unless it is hidden behind all of the manipulations you're doing with this flag variable. Whatever you're doing, it is wrong.
Here is an implementation, using your test data and using the outline I presented earlier:
#include <unordered_map>
#include <iostream>
#include <algorithm>
#include <climits>
int main()
{
std::unordered_map<int, int> numbers;
int test[] = {1, 5, 3, 4, 2, 4, 5};
// Set minimum index to a large value
int minIndex = std::numeric_limits<int>::max();
for (size_t i = 0; i < std::size(test); ++i )
{
// check if item is found
auto iter = numbers.find(test[i]);
if ( iter == numbers.end())
// not found, so add item and position
numbers.insert({test[i], i});
else
// set the minimum index to the found position and exit the loop
minIndex = std::min(minIndex, iter->second);
}
if ( minIndex == std::numeric_limits<int>::max())
std::cout << -1;
else
std::cout << minIndex;
}
Output:
1
This is effectively has O(n) runtime, as opposed to what you wrote, which was O(n^2) due to the inefficient counting loop.
despite the question, this line of code
int arr[n];
is not allowed in C++ even if your local IDE didn't give any errors I think your online judge will give a runtime error.
As the arrays in C++ must be statically allocated which means you need to know the number of elements of the array before you run the code.

push_back in empty integer vector is filling it with unexpected values?

int main()
{
using namespace std;
int n = 5,input;
vector<int> N(n);
vector<int> S;
for(int i=0;i<n;i++)
{
cin>>input;
N.push_back(input);
}
cin>>Q;
for(auto const& value: N)
{
if(value<Q)
{
S.push_back(value);
N.erase(remove(N.begin(), N.end(), value), N.end());
}
}
...
This code first pushes the values entered by user into N vector and then within for loop, if the value of the element in N vector is less than Q, then it will push that element into the empty vector S and removes that element from vector N.
For example:
N vector : 21 9 5 8 10
Q = 10
Now after the first iteration :
N vector : 21 10
S vector : 0 9 8 9 5 8
But the expected S vector is :
S vector : 9 5 8
Why I'm getting unexpected S vector values?
If your goal is to remove items from a vector that satisfies a certain condition, and add those removed items to another vector, using the STL algorithm functions will do the job instead of writing loops:
#include <algorithm>
#include <vector>
#include <iterator>
int main()
{
std::vector<int> N = { 32, 10, 22, 100, 210, 1};
std::vector<int> S;
int Q = 100;
// partition the items
auto it = std::stable_partition(N.begin(), N.end(), [&](int n) { return n < Q;});
// copy items from left partition to the vector
std::copy(N.begin(), it, std::back_inserter(S));
// erase items in left partition
N.erase(N.begin(), it);
}
Live Example
The whole idea is to use a partitioning algorithm. In this case, I used std::stable_partition to return an iterator that divides the partitioned vector.
The partition point is determined by the predicate (n < Q). Anything to the left of the partition satisfies n < Q, else the values are placed on the right of the partition.

incorrect output min stl priority queue for printing top 'm' elements

min stl priority queue for storing top 'm' elements out of the entire array is showing an incorrect output. Here in this example, the sorted vector will be [1,3,3,3,3,5,5,5,5,8,8,8,8,8]. Thus the top 'm' where m = 5 should be 1,3,3,3,3 but the output is 1,3,3,3,5. Could anyone suggest why it is not working in case of duplicate entries. Here is the sample code.
#include <iostream>
#include <queue>
using namespace std;
struct compare
{
bool operator()(const int& l, const int& r)
{
return l > r;
}
};
int main()
{
priority_queue<int,vector<int>, compare > pq;
vector <int> p;
p.push_back(3);
p.push_back(3);
p.push_back(3);
p.push_back(3);
p.push_back(5);
p.push_back(5);
p.push_back(5);
p.push_back(5);
p.push_back(1);
p.push_back(8);
p.push_back(8);
p.push_back(8);
p.push_back(8);
p.push_back(8);
for(int i=0;i<p.size();i++)
{
int k= p[i];
if(pq.size() < 5) // top 'm' elements say m = 5 here
{
pq.push(k);
}
else if (pq.top() >= k)
{
pq.pop();
pq.push(k);
}
}
while ( !pq.empty() )
{
cout << pq.top() << endl;
pq.pop();
}
cin.get();
}
The incorrect output is :
1
3
3
3
5
but the correct output should be
1
3
3
3
3
The priority queue defined by you is actually pushing values from lowest to highest from top to bottom till the point in code when priority queue size <= 5, but after that it is replacing the currently-lowest value in PQ (equals top of PQ) with the new lowest value to be pushed. Consequently, you are losing the second lowest value in resulting PQ.
Instead of replacing the lowest value with second lowest, you should be pushing out the highest one (the bottom-most in PQ), which is not possible IMO without using double queue (or stack) implementation, and also not recommended for higher time complexity.
Solution:
Change the definition of pq from
priority_queue<int,vector<int>, compare > pq;
to
priority_queue<int,vector<int>> pq;
Get the reverse of PQ to get the answer :
Do list::push_front(pq.top) and pop elements in PQ till PQ becomes empty,
and then print the list using
for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
std::cout << ' ' << *it <<endl;
Find working code here
When if(pq.size() < 5) in your iteration over p you fill the pq with
3 3 3 3 5
after that else if (pq.top() >= k) condition do the job and you replace the top value 3 with the smallest value in the p. It's 1. So finally you've got:
1 3 3 3 5
If your goal is to find and store top 5 elements of the vector, consider using std::partial_sort_copy instead of priority_queue:
std::array<int, 5> arr;
std::partial_sort_copy(p.begin(), p.end(), arr.begin(), arr.end());
This way you'll get your first 5 elements stored in arr.
Sidenote: you can use initializer list to set up your vector in one line
vector <int> p{3,3,3,3,5,5,5,5,1,8,8,8,8,8};
Working code example
You may do the following
int main()
{
std::priority_queue<int, std::vector<int>, std::less<>> pq;
for(int i : {3, 3, 3, 3, 5, 5, 5, 5, 1, 8, 8, 8, 8, 8}) {
if (pq.size() < 5 || i < pq.top()) {
pq.push(i);
}
if (pq.size() > 5)
{
pq.pop();
}
}
while (!pq.empty()) {
std::cout << pq.top() << std::endl;
pq.pop();
}
}
With a reverse display.