Not sure how to phrase this the best way but I am wanting to get unique data in reverse. It'll be better if I give an example
If I have the data
0 1
0 3
0 4
1 0
1 2
1 5
3 0
how could I get rid of the data that is a reverse of itself? For example: 0 1 and 1 0 and I would like to get rid of 1 0 because I already saw 0 1. Another example: 0 3 and 3 0 and I would like to get rid of 3 0 because I already saw 0 3.
So the data would instead be this:
0 1
0 3
0 4
1 2
1 5
Here is the code I have for how the data is coming out.
int temp;
int tn;
for (int i=0; i < n-1; i++)
{
for (int j=0; j< 4; j++)
{
temp = grid[i].neighbor[j];
tn = get_neighbor(j);
cout << i << " " << grid[i].neighbor[j] <<endl; //index
}
}
Note that it is i and grid[i].neighbor[j] that are producing the two numbers.
If you may not to change the order of elements of the original vector then the straightforward approach is the following
std::vector<std::vector<int>> v;
int a[][2] = { { 0, 1 }, { 0, 3 }, { 0, 4 }, { 1, 0 }, { 1, 2 }, { 1, 5 }, { 3, 0 } };
std::transform( std::begin( a ), std::end( a ), std::back_inserter( v ),
[]( const int ( &row )[2] )
{
return std::vector<int>( std::begin( row ), std::end( row ) );
} );
for ( const std::vector<int> &row : v )
{
for ( int x : row ) std::cout << x << ' ';
std::cout << std::endl;
}
std::cout << std::endl;
std::function<bool( const std::vector<int> &, const std::vector<int> & )> identical =
[]( const std::vector<int> &v1, const std::vector<int> &v2 )
{
return ( v1.size() == v2.size() && v1.size() == 2 &&
( v1[0] == v2[0] && v1[1] == v2[1] || v1[0] == v2[1] && v1[1] == v2[0] ) );
};
auto last = v.begin();
for ( auto first = v.begin(); first != v.end(); ++first )
{
using namespace std::placeholders;
if ( std::find_if( v.begin(), last, std::bind( identical, _1, *first ) ) == last )
{
if ( first != last ) *last = *first;
++last;
}
}
v.erase( last, v.end() );
for ( const std::vector<int> &row : v )
{
for ( int x : row ) std::cout << x << ' ';
std::cout << std::endl;
}
Of course there was no any need to define intermediate array a that to initialize the vector. You can initialize it using initializer list.
The output is
0 1
0 3
0 4
1 0
1 2
1 5
3 0
0 1
0 3
0 4
1 2
1 5
1) Sort the dataset
2) Check for duplicates (just normally, not in reverse)
3) Remove any duplicates found
4) Loop through and check each item against the reverse of each item (two for loops)
Steps 1/2/3 can be combined into step 4 for less iteration, or they can be seperated into a set. A set in C++ will automatically remove duplicates for steps 2 and 3 as well as sort your values and is a good chance to check out some STL stuff (Standard Template Library).
I have an idea on how to implement this, just for share, please do not vote down my answer..
The key point here is how to recognize two reverse pair, of course we can compare each of them, but there are surely more elegant way to do this.
If your numbers are in some fixed range integer, for example 0..10, then you can define a prime number array like this prime_arr = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31], now we can see if two pairs <x. y> and <a, b> are the same or in reverse, we can just compare prime_arr[x] * prime_arr[y] and prime_arr[a] * prime_arr[b].
Oh, it is just a sample, if your number is not in fixed range, but all non negative integer, you can consider x^2 + y^2, if two pairs <x, y> and <a, b> are the same or in reverse, compare x^2 + y^2 and a^2 + b^2.
Here is a demo implementation, hope it is useful for you...
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<pair<int, int>> v = { { 0, 1 }, { 0, 3 }, { 0, 4 },
{ 1, 0 }, { 1, 2 }, { 1, 5 }, { 3, 0 }};
vector<int> flagv;
for (auto p : v) {
int flag = p.first * p.first + p.second * p.second;
if (find(flagv.begin(), flagv.end(), flag) == flagv.end()) {
cout << p.first << " " << p.second << endl;
flagv.push_back(flag);
}
}
return 0;
}
Just one look for scanning the pair list..
Anyway, it is an advice from me, and limited usage(non negative integer), but you can figure out more proper computation to recognize two pair whether they are in reverse or the same.
just use comparator that normalize pair:
typedef std::pair<int,int> ipair;
typedef std::vector<ipair> ipvector;
inline
ipair norm( const ipair &p )
{
return ipair{ std::min( p.first, p.second ), std::max( p.first, p.second ) };
}
struct norm_cmp {
bool operator()( const ipair &p1, const ipair &p2 )
{
return norm( p1 ) < norm( p2 );
}
};
int main()
{
ipvector v = { { 0, 1 }, { 0, 3 }, { 0, 4 },
{ 1, 0 }, { 1, 2 }, { 1, 5 }, { 3, 0 }};
std::set<ipair, norm_cmp> s( v.begin(), v.end() );
for( const ipair &p : s )
std::cout << '{' << p.first << ',' << p.second << '}' << std::endl;
}
run on ideone
Related
Below there is a tabular view of a sorted vector.
vector v1= {1 , 8 ,10 ,16}
int x=9;
You are given a task to reorder vector v1 by following a rule.
You will be given a integer x.
The rule is:
You will print all the elements of the vector, such that, the numbers appearing closest to x in the vector v1 must be printed first.
For example the reordered vector must be 8,10,16,1.
sample examples:
x=15 . . .v1={-100,1,12,15,100} . . . output:{15,12,1,100,-100}
x=99 . . .v1={-100,1,12,15,100} . . . output:{100,15,12,1,-100}
x=-1 . . .v1={-100,1,12,15,100} . . . output:{1,12,15,-100,100}
In case there are two numbers that are equally closer to x, in that case, print smaller element first
for example:
x=0 . . .v1={-100,-50,50,100} . . . output:{**-50**,50,**-100**,100}
I used a naive approach, but it is too slow for larger ranges.
while(0 < v1.size()) {
for (int j = 0; j <= v1.back(); j++) {
if (x - j >= 0 && find(all(v1), x - j) != v1.end()) {
b = x - j; break;
}
if (x + j <= v1.back() && find(all(v1), x + j) != v1.end()) {
b = x + j; break;
}
}
cout<<b;
auto it2 = find(all(v1), b);
v1.erase(it2);
}
Please, if you can, suggest me a faster code.
My code is way too slow.
Elaborating on what Aconcagua suggested:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
struct sortClosestToFunctor {
explicit sortClosestToFunctor(int x) : m_x{x} {}
bool operator()(int const lhs, int const rhs) const {
int dx = std::abs(lhs - m_x);
int dy = std::abs(rhs - m_x);
return (dx < dy) or (dx == dy and lhs < rhs);
}
private:
int m_x;
};
int main() {
std::vector<int> v1{1, 8, 10, 16};
int x = 9;
// using functor
std::sort(v1.begin(), v1.end(), sortClosestToFunctor(9));
// using lambda
std::sort(v1.begin(), v1.end(), [x](int const lhs, int const rhs) {
int dx = std::abs(lhs - m_x);
int dy = std::abs(rhs - m_x);
return (dx < dy) or (dx == dy and lhs < rhs);
});
// 8 10 16 1
std::copy(v1.begin(), v1.end(), std::ostream_iterator<int>(std::cout, " "));
}
Well, you need an appropriate comparator, then you can simply use std::sort:
std::vector<int> numbers;
int referenceValue; // = ...
std::sort
(
numbers.begin, numbers.end,
[/* ... */](int x, int y) { /* ... */ }
);
You'll get the vector sorted into exactly the order you need, no need to find and remove elements from, you can just iterate over it afterwards. std::sort guarantees O(n(log(n)) (since C++11), so that should be fast enough (faster you cannot get on sorting anyway...).
Question now is: how would such a comparator look like?
Well, at very first, it will need to have the reference value available, so it will capture it:
[referenceValue](int x, int y) { /* ... */ }
As it's a simple int, capturing by value is fine, more complex types you might prefer to capture by reference instead.
The comparator should implement 'less' semantics, so it should return true if x goes before y. So we can have:
int dx = std::abs(x - referenceValue);
int dy = std::abs(y - referenceValue);
return dx < dy || dx == dy && x < y;
// if x has smaller distance: ^^^^^^^
// or, in case of equality, the smaller one ^^^^^^^^^^^^^^^^^^^^
That's it, you're done...
Untested code, if you happen to find a bug, please fix it yourself ;)
My five cents. A straightforward approach without sorting a vector.
I am sure that it is a bad idea to sort the vector if the only task is to output it in some order. Otherwise the original vector will be changed (Why?! This is not required in the assignment.) or a copy of the vector will be created.
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
std::ostream & closest_output( const std::vector<int> &v,
const int &value,
std::ostream &os = std::cout )
{
auto it = std::lower_bound( std::begin( v ), std::end( v ), value );
if ( it == std::begin( v ) )
{
for ( auto last = std::end( v ); it != last; ++it )
{
os << *it << ' ';
}
}
else if ( it == std::end( v ) )
{
for ( auto first = std::begin( v ); it != first; )
{
os << *--it << ' ';
}
}
else
{
auto next = it, first = std::begin( v ), last = std::end( v );
while ( it != first && next != last )
{
if ( *next - value < value - *std::prev( it ) )
{
os << *next++ << ' ';
}
else
{
os << *--it << ' ';
}
}
while ( it != first ) os << *--it << ' ';
while ( next != last ) os << *next++ << ' ';
}
return os;
}
int main()
{
std::vector<int> v1 = { 1 , 8 ,10 ,16 };
int value = 9;
closest_output( v1, value ) << '\n';
std::vector<int> v2 = { -100, 1, 12, 15, 100 };
value = 15;
closest_output( v2, value ) << '\n';
value = 99;
closest_output( v2, value ) << '\n';
value = 1;
closest_output( v2, value ) << '\n';
return 0;
}
The program output is
8 10 16 1
15 12 1 100 -100
100 15 12 1 -100
1 12 15 100 -100
Let's consider if x = 9 and vector = {1, 8, 10, 16},
Then upper bound of x in vector is 10,
Now if you traversal toward begin or toward end of the vector from upper bound the distance will increase with respect to x in both direction, because vector is sorted.
Following two step will produce required output,
Find distance between x and left element, and between right element and x then if left distance is less then or equal to right distance then print left element otherwise print right element,
If left element is printed then move one element previous to left element and if right element is printed then move next element from right element.
Now let`s apply these steps,
Here x = 9, vector = {1, 8, 10, 16} and upper bound = 10
left element = 8, right element = 10
(9 - 8) <= (10 - 9) is true, so print 8, and now left element = 1
left element = 1, right element = 10
(9 - 1) <= (10 - 9) is false, so print 10, and now right element = 16
left element = 1, right element = 16
(9 - 1) <= (16 - 9) is false, so print 16, and now right element = end of
vector
left element = 1, right element = end of vector
so print 1
These steps will produce expected output : {8, 10, 16, 1}
Try this implementation,
#include <iostream>
#include <vector>
#include <algorithm>
using std::cout;
template <typename ForwardIterator>
void print(ForwardIterator first, ForwardIterator last){
for(; last != first; ++first)
cout<< *first<< " ";
}
void printClostestFirst(const std::vector<int>& vec, const int piotValue){
std::vector<int>::const_iterator mid = std::upper_bound(vec.cbegin(), vec.cend(), piotValue);
if(vec.cend() == mid){
print(vec.crbegin(), vec.crend());
return;
}
else if(vec.begin() == mid){
print(vec.cbegin(), vec.cend());
return;
}
std::vector<int>::const_reverse_iterator left = vec.crbegin() + std::distance(mid, vec.cend());
std::vector<int>::const_iterator right = mid;
std::vector<int>::const_reverse_iterator leftEnd = vec.crend();
std::vector<int>::const_iterator rightEnd = vec.cend();
int leftDist = 0;
int rightDist = 0;
while(leftEnd != left && rightEnd != right){
leftDist = piotValue - *left;
rightDist = *right - piotValue;
if(leftDist <= rightDist){
cout<< *left<< " ";
++left;
}
else{
cout<< *right<< " ";
++right;
}
}
if(leftEnd != left)
print(left, leftEnd);
else
print(right, rightEnd);
}
int main(int , char *[]){
cout<< "x = 9 . . .vec = { 1, 8, 10, 16 } . . . output: { ";
printClostestFirst({1, 8, 10, 16}, 9);
cout<< "}\n";
cout<< "x = 15 . . .vec = { -100,1,12,15,100 } . . . output: { ";
printClostestFirst({-100,1,12,15,100}, 15);
cout<< "}\n";
cout<< "x = 99 . . .vec = { -100,1,12,15,100 } . . . output: { ";
printClostestFirst({-100,1,12,15,100}, 99);
cout<< "}\n";
cout<< "x = -1 . . .vec = { -100,1,12,15,100 } . . . output: { ";
printClostestFirst({-100,1,12,15,100}, -1);
cout<< "}\n";
cout<< "x = 0 . . .vec = { -100,1,12,15,100 } . . . output: { ";
printClostestFirst({-100,-50,50,100}, 0);
cout<< "}\n";
}
output:
x = 9 . . .vec = { 1, 8, 10, 16 } . . . output: { 8 10 16 1 }
x = 15 . . .vec = { -100,1,12,15,100 } . . . output: { 15 12 1 100 -100 }
x = 99 . . .vec = { -100,1,12,15,100 } . . . output: { 100 15 12 1 -100 }
x = -1 . . .vec = { -100,1,12,15,100 } . . . output: { 1 12 15 -100 100 }
x = 0 . . .vec = { -100,1,12,15,100 } . . . output: { -50 50 -100 100 }
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 3 years ago.
Improve this question
I dont understand why the condition of if-statement needs to be a pointer. I assumed a normal variable call will not give any complaints.
Was trying to learn about std::vector::erase from cppreference, got intrigued about the example there (https://en.cppreference.com/w/cpp/container/vector/erase)
#include <vector>
#include <iostream>
int main( )
{
std::vector<int> c{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
for (auto &i : c) {
std::cout << i << " ";
}
std::cout << '\n';
// Erase all even numbers (C++11 and later)
for (auto it = c.begin(); it != c.end(); ) {
if (*it % 2 == 0) {
it = c.erase(it); // THE LINE ABOVE THIS
} else {
++it;
}
}
for (auto &i : c) {
std::cout << i << " ";
}
std::cout << '\n';
}
Output
0 1 2 3 4 5 6 7 8 9
1 3 5 7 9
Hope anyone could share an explanation or direct me to an available resource.
In the classical loop:
auto it = c.begin() - it is an iterator. To access what it refers to you need to dereference it, which you do with *it. The * there does not mean pointer, it means dereference (technically, on iterators, it's a call to operator*).
See also https://en.cppreference.com/w/cpp/iterator
In the range based loop:
for (auto &i : c) - here you get back a reference to the element in the container directly. No iterators involved.
Ranged based for-loop: necessity of pointer variable as condition in
if-statement
I think that the confusion is that you are incorrectly considering the ordinary for-loop
for (auto it = c.begin(); it != c.end(); )
as the ranged for-loop.
In your program the range-based for loop is used only to output the vector.
for (auto &i : c) {
std::cout << i << " ";
}
Iterators behave as pointers. That is for them for example there are defined operator * and operator ++.
Consider a similar program that deals with an array. Of course you can not remove elements from an array but you can move "removed" elements to the end of the array.
Here is a demonstrative program.
#include <iostream>
int main()
{
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
const size_t N = sizeof( a ) / sizeof( *a );
for ( const int *p = a; p != a + N; ++p )
{
std::cout << *p << ' ';
}
std::cout << '\n';
int *q = a;
for ( const int *p = a; p != a + N; ++p )
{
if ( not ( *p % 2 == 0 ) )
{
if ( p != q ) *q = *p;
++q;
}
}
for ( const int *p = a; p != q; ++p )
{
std::cout << *p << ' ';
}
std::cout << '\n';
return 0;
}
Its output is
0 1 2 3 4 5 6 7 8 9
1 3 5 7 9
As you can see in this if statement
if ( not ( *p % 2 == 0 ) )
you have to dereference the pointer to get the value pointed to by the pointer.
Now rewrite the program the following way using generic functions std::begin, std::cbegin, and std::cend.
#include <iostream>
#include <iterator>
int main()
{
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for ( auto p = std::cbegin( a ); p != std::cend( a ); ++p )
{
std::cout << *p << ' ';
}
std::cout << '\n';
auto q = std::begin( a );
for ( auto p = std::cbegin( a ); p != std::end( a ); ++p )
{
if ( not ( *p % 2 == 0 ) )
{
if ( p != q ) *q = *p;
++q;
}
}
for ( auto p = std::begin( a ); p != q; ++p )
{
std::cout << *p << ' ';
}
std::cout << '\n';
return 0;
}
Now the pointers look like iterators and nothing was changed in the if statement
if ( not ( *p % 2 == 0 ) )
I'm trying to improve my c++ knowledge using Edabit challenges and testing out 'new' functions. Current challenge wants us to write a function to reverse an array.
examples:
reverse([1, 2, 3, 4]) ➞ [4, 3, 2, 1]
reverse([9, 9, 2, 3, 4]) ➞ [4, 3, 2, 9, 9]
reverse([]) ➞ []
I tried to do this using reverse_iterator, but I have some odd result.
std::vector<int> reverse(std::vector<int> arr) {
std::vector<int> out;
for(std::vector<int>::reverse_iterator i = arr.rbegin(); i != arr.rend(); ++i)
{
out.push_back(arr[*i]);
}
return out;
}
The result I get is the following:
FAILED: Expected: equal to [ 4, 3, 2, 1 ]
Actual: [ 0, 4, 3, 2 ]
First it seems like it was just one off, o I added 1 with rbegin() and rend as follows:
for(std::vector<int>::reverse_iterator i = arr.rbegin() + 1; i != arr.rend() + 1; ++i)
And it seems that the first test passed, but following test seems way off:
FAILED: Expected: equal to [ 7, 6, 5 ]
Actual: [ 33, 0, 5 ]
I'm trying to understand how this reverse iterator is working, so please provide a solution and some clear explanation why the first test passed with the addition of 1 and why the second did not pass.
Try:
for(std::vector<int>::reverse_iterator i = arr.rbegin(); i != arr.rend(); ++i)
{
out.push_back(*i);
}
Iterator already gives you a value, not an index into a vector.
The expression in the subscript operator
out.push_back(arr[*i]);
^^^^^^^
does not make sense.
You mean
out.push_back( *i );
But in any case the function can be written better either like this to create a new reversed vector
#include <iostream>
#include <vector>
#include <iterator>
std::vector<int> reverse( const std::vector<int> &v )
{
std::vector<int> out;
out.reserve( v.size() );
for ( auto first = std::rbegin( v ), last = std::rend( v ); first != last; ++first )
{
out.push_back( *first );
}
return out;
}
int main()
{
std::vector<int> v = { 4, 3, 2, 1 };
for ( const auto &item : v ) std::cout << item << ' ';
std::cout << '\n';
auto reversed_v = reverse( v );
for ( const auto &item : reversed_v ) std::cout << item << ' ';
std::cout << '\n';
return 0;
}
The program output is
4 3 2 1
1 2 3 4
Or like this to reverse a vector in place
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
void reverse( std::vector<int> &v )
{
if ( not v.empty() )
{
for ( auto first = std::rbegin( v ), last = std::rend( v ); first < --last; ++first )
{
std::iter_swap( first, last );
}
}
}
int main()
{
std::vector<int> v = { 4, 3, 2, 1 };
for ( const auto &item : v ) std::cout << item << ' ';
std::cout << '\n';
reverse( v );
for ( const auto &item : v ) std::cout << item << ' ';
std::cout << '\n';
return 0;
}
The program output is the same as shown above
4 3 2 1
1 2 3 4
Alternatively there are corresponding standard algorithms std::reverse_copy and std::reverse that you can use instead.
Prefer algorithms in the standard library to hand crafted loops as much as possible because:
1) they are more expressive;
2) they are likely to be more efficient.
std::reverse(std::begin(arr), std::end(arr));
Just include the 'algorithm' header to use std::reverse.
I am writing an exercises on codility via c++. Here the question:
A non-empty zero-indexed array A consisting of N numbers is given. The
array is sorted in non-decreasing order. The absolute distinct count
of this array is the number of distinct absolute values among the
elements of the array.
For example, consider array A such that:
A[0] = -5
A[1] = -3
A[2] = -1
A[3] = 0
A[4] = 3
A[5] = 6
The absolute distinct count of this array is 5, because there are 5 distinct absolute values among the elements of this array,
namely 0, 1, 3, 5 and 6.
Write a function:
int solution(vector<int> &A);
that, given a non-empty zero-indexed array A consisting of N numbers,
returns absolute distinct count of array A.
For example, given array A such that:
A[0] = -5
A[1] = -3
A[2] = -1
A[3] = 0
A[4] = 3
A[5] = 6
the function should return 5, as explained above.
Assume that:
N is an integer within the range [1..100,000];
each element of array A
is an integer within the range [−2,147,483,648..2,147,483,647];
array
A is sorted in non-decreasing order.
Complexity:
expected worst-case time complexity is O(N);
expected worst-case space
complexity is O(N), beyond input storage (not counting the storage
required for input arguments).
Elements of input arrays can be
modified.
I am writing down the following code, and I fail to find any problems in my code, but it just doesn't pass.
#include <algorithm>
#include <vector>
#include <cmath>
int solution(vector<int> &A) {
int N(A.size());
vector<long long> B(N,0);
int counter(1);
//int index(0);
int move1(0);
int move2(N-1);
if(N==1)
{return 1;}
if(N==0)
{return 0;}
if(N==2)
{
if(abs(A[0])==abs(A[1]))
{return 1;}
else{return 2;}
}
for (int i = 0 ; i < N ; ++i)
{
B[i]=abs((long long )A[i]);
}
while(move1<move2)
{
if(B[move1]==B[move1+1])
{move1+=1;}
else if(B[move2]==B[move2]-1)
{move2-=1;}
else if(B[move1]>B[move2])
{
counter+=1;
move1+=1;
}
else if(B[move1]<B[move2])
{
counter+=1;
move2-=1;
}
else{move1+=1;}
}
return counter;
}
Here's the link of performance, https://codility.com/demo/results/trainingUT9QAN-JMM/
There's some errors but I can't figure out its detail, if anyone could help me with my code, I will really appreciate!
Thanks!
You may want to have an iterative solution. Start from both ends and work your way inward toward 0.
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
size_t solution( const std::vector< int > & A )
{
std::vector< int >::const_iterator f( A.begin() );
std::vector< int >::const_reverse_iterator b( A.rbegin() );
size_t result = 0;
if( A.size() )
for( ; ( f != A.end() ) && ( b != A.rend() ); )
{
if( *f >= 0 )
return result + ( ( A.end() - f ) - ( b - A.rbegin() ) );
else if( *b <= 0 )
return result + ( ( A.rend() - b ) - ( f - A.begin() ) );
else if( *f == -*b )
++result, ++f, ++b;
else if( *f > -*b )
++result, ++b;
else
++result, ++f;
}
return result;
}
int main( int, char ** )
{
std::cout << solution( std::vector< int >{ -5, -3, -1, 0, 3, 6} ) << std::endl;
std::cout << solution( std::vector< int >{ -5, -3, -1, 0, 1, 3, 6} ) << std::endl;
std::cout << solution( std::vector< int >{ -5, -3, -1, 0, 2, 3, 6} ) << std::endl;
std::cout << solution( std::vector< int >{ -5, -3, -1, 3, 6} ) << std::endl;
std::cout << solution( std::vector< int >{ -5, -3, -1, 0, 3, 4, 5} ) << std::endl;
return 0;
}
100% solution with Ruby
def solution(a)
a.each_with_object({}){ |el, acc| acc[el.abs] = true }.size
end
Got 100/100 using Java 8 streams.
return (int) Arrays.stream(A).map(Math::abs)
.distinct().count();
def solution(A):
# Creates an empty hashset
s = set()
n = len(A)
res = 0
for i in range(n):
# If not present, then put it in
# hashtable and increment result
if (A[i] not in s):
s.add(A[i])
res += 1
return res
I have a unsymmetrical vector in 2D.
vector< vector<int> > Test
where Test =
2 4 6 5 7
6 5 7 9 10
5 9 10
9 10
I am reading the row 1 and if any element of this is present in other rows then delete it.
for eaxmple.. After reading row 1, i have to remove 6, 5, and 7 from other rows.
However, It is not working
Here is the code i am trying
Test[i].erase(Test[i].begin()+j);
where i = row and j is col.
My code is :
for (i =0; i < Test.size();i++)
{
for (j=0; j < Test[i].size();j++)
{
// removed repeated element
if (i >0)
{
Test[i].erase(Test[i].begin() +j);
}
}
}
Maybe it is nor very nice but it works
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
int main()
{
std::vector<std::vector<int>> v =
{
{ 2, 4, 6, 5, 7 },
{ 6, 5, 7, 9, 10 },
{ 5, 9, 10 },
{ 9, 10 }
};
for ( const auto &row : v )
{
for ( int x : row ) std::cout << x << ' ';
std::cout << std::endl;
}
std::cout << std::endl;
if ( !v.empty() )
{
for ( auto it = std::next( v.begin() ); it != v.end(); ++it )
{
auto is_present = [&]( int x )
{
return std::find_if( v.begin(), it,
[x]( const std::vector<int> &v1 )
{
return std::find( v1.begin(), v1.end(), x ) != v1.end();
} ) != it;
};
it->erase( std::remove_if( it->begin(), it->end(), is_present ),
it->end() );
}
}
for ( const auto &row : v )
{
for ( int x : row ) std::cout << x << ' ';
std::cout << std::endl;
}
return 0;
}
The output is
2 4 6 5 7
6 5 7 9 10
5 9 10
9 10
2 4 6 5 7
9 10
You can place the values encountered in each row in a set, and then query every element in a new row for existence in that set. Such a function would look like this :
void RemoveRowDuplicates(vector<vector<int>> &v)
{
std::set<int> vals;
for(auto &vec : v)
{
vec.erase(remove_if(vec.begin(), vec.end(), [&](int k){
return vals.find(k) != vals.end();
}), vec.end());
vals.insert(vec.begin(), vec.end());
}
}
What exactly do you think is Test[i].begin()+j? Is ist a set of elements you want to erase? I don't think so. It should be just an iterator, that points to a single element, but you want to delete all elements, that are already in your datastructure.
If I understood, what you want to do, try:
for(int j = 0; j < Test.size(); j++){ //iterate over other rows
if(j == i)
continue;
for(int k = 0; k < Test[j].size(); k++){ //iterate over elements of the rows
int elementToRemove = (Test[j])[k];
vector<int>::iterator it = Test[i].begin();
while (it != Test[i].end()) { //iterate over row i
if((*it) == elementToRemove){ //erase the element if it matches the actual
it = Test[i].erase(it);
}else{
it++;
}
}
}
}
You could execute the code for every possible i. Maybe start form i = 0 to n. If I refer to your code, that you added put the code above in between your
for (i =0; i < Test.size();i++){
//my code here...
}
Edit: Used iterator now to delete. The first version was not correct.
Edit2: Changed the index of the first loop and added continue statement.
This works for me:
int i = 0;
for ( int j = i+1; j < Test.size(); ++j )
{
for ( int k = 0; k < Test[i].size(); ++k )
{
std::vector<int>::iterator iter = Test[j].begin();
std::vector<int>::iterator end = Test[j].end();
for ( ; iter != end; )
{
if ( *iter == Test[i][k] )
{
iter = Test[j].erase(iter);
}
else
{
++iter;
}
}
}
}
Consider the following 2D vector
myVector=
1 2 3 4 5 -6
6 7 8 -9
8 -1 -2 1 0
Suppose we want to delete the element myVector[row][column] for appropriate row and column indices.
Look at the following code:
void delete_element(vector<int>& temp, col)
{
temp.erase(temp.begin()+col);
}
int main()
{
//Assume that the vector 'myVector' is already present.
cin>>row>>column;
delete_element(myVector[row],column);
}
What we basically do is,we get the row and column of the element to be deleted. Now as this 2D vector is a vector of vectors, we pass the vector(the row containing the element to be deleted) and the column as parameters to a function. Note that the row-vector is passed as a reference ('&' in vector parameter).
Now the problem becomes quite as simple as deleting an element from a 1D vector.
Hope this helps!