I have the following program:
std::vector<int> nums = {1, 2, 3, 4, 5};
std::vector<int> nums2 = {5, 4, 3, 2, 1};
bool equal = std::equal(nums.begin(), nums.end(), nums2.begin());
if (equal)
{
cout << "Both vectors are equal" << endl;
}
There are two vectors that have equal elements. std::equal function does not work here because it goes sequentially and compares corresponding elements. Is there a way to check that both these vectors are equal and get true in my case without sorting? In real example I do not have integers but custom objects which comparing as equality of pointers.
You can construct a std::unordered_set from each vector, then compare those, as shown in the code snippet below:
#include <iostream>
#include <vector>
#include <unordered_set>
using namespace std;
int main()
{
std::vector<int> nums = { 1, 2, 3, 4, 5 };
std::vector<int> nums2 = { 5, 4, 3, 2, 1 };
std::vector<int> nums3 = { 5, 4, 9, 2, 1 };
std::unordered_set<int> s1(nums.begin(), nums.end());
std::unordered_set<int> s2(nums2.begin(), nums2.end());
std::unordered_set<int> s3(nums3.begin(), nums3.end());
if (s1 == s2) {
std::cout << "1 and 2 are equal";
}
else {
std::cout << "1 and 2 are different";
}
std::cout << std::endl;
if (s1 == s3) {
std::cout << "1 and 3 are equal";
}
else {
std::cout << "1 and 3 are different";
}
std::cout << std::endl;
return 0;
}
However, there are some points to bear in mind:
For vectors of custom type objects, you would need to provide an operator== for that type (but that would have to be done anyway, or how can you say if the two vectors have the same contents).
Vectors that containing duplicate entries will create sets that have those duplicates removed: Thus, {1, 2, 2, 3} will show equal to {1, 2, 3}.
You will also need to provide a std:hash for your custom type. For a trivial class, bob, which just wraps an integer, that hash, and the required operator==, could be defined as shown below; you can then replace the <int> specializations in the above example with <bob> and it will work. (This cppreference article explains more about the hash.)
class bob {
public:
int data;
bob(int arg) : data{ arg } { }
};
bool operator==(const bob& lhs, const bob& rhs)
{
return lhs.data == rhs.data;
}
template<> struct std::hash<bob> {
std::size_t operator()(bob const& b) const noexcept {
return static_cast<size_t>(b.data);
}
};
The std::is_permutation standard library algorithm does exactly what you want. It returns true if both ranges contain the same elements in any order.
It might be slow for some applications but it only requires equality comparison and it doesn't require a temporary container or additional memory allocation.
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> nums = { 1, 2, 3, 4, 5 };
std::vector<int> nums2 = { 5, 4, 3, 2, 1 };
bool equal = std::is_permutation(nums.begin(), nums.end(), nums2.begin(), nums2.end());
if (equal) {
std::cout << "Both vectors are equal" << std::endl;
}
}
You're looking for a set or a multiset. C++ standard library does have implementations of these data structures:
std::set
std::multiset
std::unordered_set
std::unordered_multiset
If I had to invent an algorithm to do this from scratch, because for whatever reason using sets or sorts doesn't work, I would consider removing matches. This will be inefficient - it's O(n^2) - but it will work, and inefficiency is unlikely to be an issue in many cases:
bool compare(A, B)
copy B to BB
for each a in A
if BB contains a
remove a from BB
else
return false
if BB is empty
return true
return false
Throwing-in one more way to solve your task, using std::sort. It also works correctly if vectors have duplicate elements (as seen from example below). It is also quite fast, O(N*Log(N)) time on average, in real life will be close in time to solutions with std::unordered_set or std::unordered_multiset.
Yes, I see that OP asked to achieve without sorting, but actually std::is_permutation is also doing sorting underneath almost for sure. And std::set does indirectly sorting too using trees. Even std::unordered_set does a kind of sorting by hash value (hash bucketing is a kind of radix sorting). So probably this task can't be solved without a kind of indirect sorting or other kind of ordering whole vector.
Try it online!
#include <algorithm>
#include <vector>
#include <iostream>
int main() {
std::vector<int> nums1 = {1, 2, 3, 4, 1, 5}, nums2 = {5, 4, 3, 1, 2, 1};
std::sort(nums1.begin(), nums1.end());
std::sort(nums2.begin(), nums2.end());
std::cout << std::boolalpha << (nums1 == nums2) << std::endl;
}
Output:
true
Related
As the title says, I'm looking for a way to sort a vector without modifying the original one.
My first idea is of course to create a copy of the vector before the sort, e.g.:
std::vector<int> not_in_place_sort(const std::vector<int>& original)
{
auto copy = original;
std::sort(copy.begin(), copy.end());
return copy;
}
However, maybe there is a more efficient way to perform the sort using C++ standard algorithm (maybe a combination of sort and transform?)
Use partial_sort_copy. Here is an example:
vector<int> v{9,8,6,7,4,5,2,0,3,1};
vector<int> v_sorted(v.size());
partial_sort_copy(begin(v), end(v), begin(v_sorted), end(v_sorted));
Now, v remains untouched but v_sorted contains {0,1,2,3,4,5,6,7,8,9}.
Here is my favorite. Sort an index and not the original array/vector itself.
#include <algorithm>
int main() {
int intarray[4] = { 2, 7, 3, 4 };//Array of values
//or you can have vector of values as below
//std::vector<int> intvec = { 2, 7, 3, 4 };//Vector of values
int indexofarray[4] = { 0, 1, 2, 3 };//Array indices
std::sort(indexofarray, indexofarray + 4, [intarray](int index_left, int index_right) { return intarray[index_left] < intarray[index_right]; });//Ascending order.
//have intvec in place of intarray for vector.
}
After this, indexofarray[] elements would be 0, 2, 3, 1, while intarray[] is unchanged.
As suggested in the comments pass the function argument by value std::vector<int> original:
#include <iostream>
#include <vector>
#include <algorithm>
std::vector<int> not_in_place_sort(std::vector<int> original) {
std::sort(original.begin(), original.end());
return original;
}
int main() {
std::vector<int> v = { 8, 6, 7, 2, 3, 4, 1, 5, 9 };
std::vector<int> v2 = not_in_place_sort(v); // pass the vector by value
std::cout << "v1: " << '\n';
for (auto el : v) {
std::cout << el << ' ';
}
std::cout << "\nv2: " << '\n';
for (auto el : v2) {
std::cout << el << ' ';
}
}
That will sort a copy of your original vector leaving the original intact.
As pointed out below this might restrict some optimizations such as RVO but will call vector's move constructor in the return statement instead.
For the case where you are interested in proxy sorting (sorting an index list), you may want to implement a more flexible algorithm that allows you to deal with containers which do not support random access (such as std::list). For example:
#include <algorithm>
#include <iostream>
#include <list>
#include <numeric>
#include <vector>
template <typename Container>
auto sorted_indices(const Container& c) {
std::vector<typename Container::size_type> indices(c.size());
std::iota(indices.begin(), indices.end(), 0);
std::sort(indices.begin(), indices.end(), [&c](auto lhs, auto rhs) {
return (*(std::next(c.begin(), lhs)) < *(std::next(c.begin(), rhs)));
});
return indices;
}
template <typename Container, typename Indices>
auto display_sorted(const Container& c, const Indices& indices) {
std::cout << "sorted: ";
for (auto&& index : indices) {
std::cout << *(std::next(c.begin(), index)) << " ";
}
std::cout << std::endl;
}
template <typename Container>
auto display_sorted(const Container& c) {
return display_sorted(c, sorted_indices(c));
}
template <typename Container>
auto display(const Container& c) {
std::cout << "as provided: ";
for (auto&& ci : c) std::cout << ci << " ";
std::cout << std::endl;
}
int main() {
// random access
const std::vector<int> a{9, 5, 2, 3, 1, 6, 4};
display(a);
display_sorted(a);
display(a);
std::cout << "---\n";
// no random access
const std::list<int> b{9, 5, 2, 3, 1, 6, 4};
display(b);
display_sorted(b);
display(b);
}
Sample run:
$ clang++ example.cpp -std=c++17 -Wall -Wextra
$ ./a.out
as provided: 9 5 2 3 1 6 4
sorted: 1 2 3 4 5 6 9
as provided: 9 5 2 3 1 6 4
---
as provided: 9 5 2 3 1 6 4
sorted: 1 2 3 4 5 6 9
as provided: 9 5 2 3 1 6 4
As you would expect, relying on proxy sorting could have important performance implications. For example: every time you want to traverse in order, you will possibly incur cache misses. In addition, the traversal will have the same complexity as the underlying container for random access: In the case of std::vector, std::next(v.begin(), n) is O(1), but in the case of std::list, std::next(l.begin(), n) is O(n).
For int's it doesn't make much difference if you're sorting an index or making a copy & sorting the copy; the data still needs to be initialized, and in the case of the indexes, this will involve a loop assigning values rather than faster memcpy routines; so may end up slower; in addition you're going to be jumping around memory lots more; so now the cache can't do its job nicely.
For larger objects I'd not sort the index, but use a vector of pointers. The copy of the pointers is cheap compared to copying the objects themselves; the containers are still obvious because they're containing pointers of your object; and the sort isn't attempting to reference another vector.
You can create another vector to store the indices. Here is the code:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
vector<int> numbers = {50,30,20,10,40};
vector<int> indexOfNumbers;
for(int i = 0; i < numbers.size(); i++)
{
indexOfNumbers.push_back(i);
}
// Now, indexOfNumbers = [0,1,2,3,4]
std::sort(
indexOfNumbers.begin(), indexOfNumbers.end(),
[numbers](int leftIndex, int rightIndex)
{
return numbers[leftIndex] < numbers[rightIndex]; // sort in ascending order
}
);
// After sorting, indexOfNumbers = [3, 2, 1, 4, 0]
// Access the sorted elements
cout << "Accessing the sorted elements : ";
for(int i = 0; i < numbers.size(); i++)
{
cout << numbers[indexOfNumbers[i]] << " ";
}
// prints numbers in sorted order i.e. [10,20,30,40,50]
return 0;
}
Source: Made slight modification according to Tyrer's answer (https://stackoverflow.com/a/47537314)
Among the functionalities found in std::algorithm I can't seem to find one of the most basic I can think of: selected a subset of a collection (for example, return all the odd numbers, all the employees that have status == 'employed', all items that cost less that 20 dollars).
So, given a list of ints like
vector<int> ints {1, 9, 3, 27, 5, 19, 3, 8, 2, 12};
vector<int> evens = ?
vector<int> greaterThan7 = ?
How to find those that are even and those that are greater than 7?
If you want something more functional, you can check out the boost range library. Specifically, filtered:
for (int i : ints | filtered([](int i){return i > 7;}))
{
...
}
This gives you a lazy view, without constructing a new container.
You can get the same from Eric Niebler's range-v3:
for (int i : view::filter(ints, [](int i){return i > 7;})
{
...
}
with the benefit that you can just assign that to a vector too (so you can choose if it's lazy or eager, which Boost.Ranges does not allow).
std::vector<int> greaterThan7 = view::filter(ints, [](int i){return i > 7;});
std::vector<int> sameThing = ints | view::filter([](int i){return i > 7;});
For example
vector<int> ints {1, 9, 3, 27, 5, 19, 3, 8, 2, 12};
vector<int> evens;
std::copy_if( ints.begin(), ints.end(), std::back_inserter( evens ),
[]( int x ) { return x % 2 == 0; } );
Here is a demonstrative program
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
int main()
{
std::vector<int> ints { 1, 9, 3, 27, 5, 19, 3, 8, 2, 12 };
std::vector<int> evens;
std::copy_if( ints.begin(), ints.end(), std::back_inserter( evens ),
[]( int x ) { return x % 2 == 0; } );
for ( int x : evens ) std::cout << x << ' ';
std::cout << std::endl;
}
Its output is
8 2 12
Depending on what your exact requirements are, consider std::stable_partition (or std::partition). It reorders elements in the range such that all which satisfy a predicate come first. You can think of it as splitting the range into a "subset" and a "not subset" part. Here is an example:
#include <algorithm>
#include <vector>
#include <iostream>
int main()
{
using std::begin;
using std::end;
using std::cbegin;
using std::cend;
std::vector<int> ints { 1, 9, 3, 27, 5, 19, 3, 8, 2, 12 };
auto const greater_than_7 = [](int number) { return number > 7; };
auto const iter_first_not_greater_than_7 = std::stable_partition(begin(ints), end(ints), greater_than_7);
for (auto const_iter = cbegin(ints); const_iter != iter_first_not_greater_than_7; ++const_iter)
{
std::cout << *const_iter << "\n";
}
}
If, however, you are fine with copying each matching element to a new collection, for example because the source range must not be modified, then use std::copy_if.
Perhaps what you are really looking for is a view of an unmodifiable range. In this case, you are approaching the problem from the wrong direction. You don't need a particular algorithm; a more natural solution to the problem would be a filtering iterator, like for example Boost's Filter Iterator. You can use the one in Boost or study its implementation to learn how you could write filtering iterators yourself.
To find the number of distinct numbers in an array from the lth to the rth index, I wrote a code block like:
int a[1000000];
//statements to input n number of terms from user in a.. along with l and r
int count=r-l+1; //assuming all numbers to be distinct
for(; l<=r; l++){
for(int i=l+1; i<=r; i++){
if(a[l]==a[i]){
count--;
break;
}
}
}
cout<<count<<'\n';
Explanation
For an array say, a=5 6 1 1 3 2 5 7 1 2 of ten elements. If we wish to check the number of distinct numbers between a[1] and a[8] that is the second and the 9th elements (including both), The logic I tried to implement would first take count=8 (no. of elements to be considered) and then it starts from a[1] that is 6 and checks for any other 6 after it, if it does find, it decreases the count by one and goes on for the next number in the row. So that if there are any more occurrence of 6 after that one, it would not be included twice.
Problem I tried small test cases and it works. But when I tried with bigger data, it did not work, so I wanted to know where would my logic fail?
Bigger data, as in integrated with other parts of the program and then used. Which gave incorrect output
You can try to use std::set
Basic idea is to add all the elements into your new set, and just output the size of your set.
#include <iostream>
#include <vector>
#include <set>
using namespace std;
int main()
{
int l = 1, r = 6;
int arr[] = {1, 1, 2, 3, 4, 5, 5, 5, 5};
set<int> s(&arr[l], &arr[r + 1]);
cout << s.size() << endl;
return 0;
}
Here is an answer that does not use std::set, although that solution is probably simpler.
#include <algorithm>
#include <vector>
int main()
{
int input[10]{5, 6, 1, 1, 3, 2, 5, 7, 1, 2}; //because you like raw arrays, I guess?
std::vector<int> result(std::cbegin(input), std::cend(input)); //result now contains all of input
std::sort(std::begin(result), std::end(result)); //result now holds 1 1 1 2 2 3 5 5 6 7
result.erase(std::unique(std::begin(result), std::end(result)), std::end(result)); //result now holds 1 2 3 5 6 7
result.size(); //gives the count of distinct integers in the given array
}
Here it is live on Coliru if you're into that.
--
EDIT: Here, have a short version of the set solution, too.
#include <set>
int main()
{
int input[10]{5, 6, 1, 1, 3, 2, 5, 7, 1, 2}; //because you like raw arrays, I guess?
std::set<int> result(std::cbegin(input), std::cend(input));
result.size();
}
The first question to ask with this type of problem is what is the possible range of the values. if the range of numbers N is "reasonably small", then you can use a boolean array of size N to indicate whether the number corresponding to the index is present. You iterate from l to r, setting the flag, and if the flag was not already set increment a counter.
count = 0;
for(int i=l; i<=r; i++) {
if (! isthere[arr[i]]) {
count++;
isthere[arr[i]] = TRUE;
}
}
In terms of complexity, both this approach and the one based on set are O(n), but this one is faster as there is no hashing involved. For small N, for example for numbers between 0-255, most likely this is also likely to be less memory intensive. For larger N, for example if any 32-bit integers is allowed, the set based approach is more suitable.
You said you didn't mind another solution. So here it is. It uses set - a structure that stores only unique elements. By the way, on the bigger data - it will much faster than solution with two cycles.
set<int> a1;
for (int i = l; i <= r; i++)
{
a1.insert(a[i]);
}
cout << a1.size();
In the below process I'm giving process of counting unique numbers. In this technique you just get unique elements in an array. this process will update your array with garbage value. So in this process you can't use this array (that we will use) further anymore. This array will automatically resize with distinct elements.
#include <stdio.h>
#include <iostream>
#include <algorithm> // for using unique (library function)
int main(){
int arr[] = {1, 1, 2, 2, 3, 3};
int len = sizeof(arr)/sizeof(*arr); // finding size of arr (array)
int unique_sz = std:: unique(arr, arr + len)-arr; // Counting unique elements in arr (Array).
std:: cout << unique_sz << '\n'; // Printing number of unique elements in this array.
return 0;
}
If you want to handle that problem (That I told before), you can follow this process. You can handle this by coping your array in another array.
#include <stdio.h>
#include <iostream>
#include <algorithm> // for using copy & unique (library functions)
#include <string.h> // for using memcpy (library function)
int main(){
int arr[] = {1, 1, 2, 2, 3, 3};
int brr[100]; // we will copy arr (Array) to brr (Array)
int len = sizeof(arr)/sizeof(*arr); // finding size of arr (array)
std:: copy(arr, arr+len, brr); // which will work on C++ only (you have to use #include <algorithm>
memcpy(brr, arr, len*(sizeof(int))); // which will work on C only
int unique_sz = std:: unique(arr, arr+len)-arr; // Counting unique elements in arr (Array).
std:: cout << unique_sz << '\n'; // Printing number of unique elements in this array.
for(int i=0; i<len; i++){ // Here is your old array, that we store to brr (Array) from arr (Array).
std:: cout << brr[i] << " ";
}
return 0;
}
Personally, I'd just use standard algorithms
#include<algorithm>
#include <iostream>
int main()
{
int arr[] = {1, 1, 2, 3, 4, 5, 5, 5, 5};
int *end = arr + sizeof(arr)/sizeof(*arr);
std::sort(arr, end);
int *p = std::unique(arr, end);
std::cout << (int)(p - arr) << '\n';
}
This obviously relies on being allowed to modify the array (any duplicates are moved to the end of arr). But it is easy to create a copy of an array if needed and work on the copy.
TL;DR: Use this:
template<typename InputIt>
std::size_t countUniqueElements(InputIt first, InputIt last) {
using value_t = typename std::iterator_traits<InputIt>::value_type;
return std::unordered_set<value_t>(first, last).size();
}
There are two approaches:
Insert everything into a set, count the set. Because you don't care about the order you can use a std::unordered_set which will be faster than std::set. std::set is implemented as a tree which does a lot of allocations so it can be slow.
Use std::sort. If you want to preserve the original array you'll need to make a copy of it.
Here is a complete example.
#include <algorithm>
#include <cstdint>
#include <vector>
#include <unordered_set>
#include <iostream>
template<typename RandomIt>
std::size_t countUniqueElementsSort(RandomIt first, RandomIt last) {
if (first == last)
return 0;
std::sort(first, last);
std::size_t count = 1;
auto val = *first;
while (++first != last) {
if (*first != val) {
++count;
}
val = *first;
}
return count;
}
template<typename InputIt>
std::size_t countUniqueElementsSet(InputIt first, InputIt last) {
using value_t = typename std::iterator_traits<InputIt>::value_type;
return std::unordered_set<value_t>(first, last).size();
}
int main() {
std::vector<int> v = {1, 3, 4, 4, 3, 6};
std::cout << countUniqueElementsSet(v.begin(), v.end()) << "\n";
std::cout << countUniqueElementsSort(v.begin(), v.end()) << "\n";
int v2[] = {1, 3, 4, 4, 3, 6};
std::cout << countUniqueElementsSet(v2, v2 + 6) << "\n";
std::cout << countUniqueElementsSort(v2, v2 + 6) << "\n";
}
Using that loop in the sort version should be faster than std::unique.
The complexity of 2. is worse than 1. - the average case is O(N) vs O(N log N). But it avoids allocation so may end up being faster for small arrays or ones that are already sorted or mostly already sorted.
You should definitely not use std::set, and probably not use std::unique (though it does lead to fewer lines of code, and won't make that much difference to performance so up to you).
In any case, in most cases you should go with the set version - it's a lot simpler simpler and should be faster in almost all cases.
As other people have mentioned, if you know your input domain is small you can use a bool array instead of an unordered_set.
I would like to compare vector with an array. Elements in vector and in array are in different order, unsorted and can duplicated. E.g.
Below are the same:
vector<int> lvector = {5,7,3,1,2,7};
int larray[6] = {3,5,1,7,2,7}
Below, not the same:
vector<int> lvector = {5,7,3,1,2,7,5};
int larray[7] = {3,5,1,7,2,7,3}
And something like this is also not the same:
vector<int> lvector = {1,1,1,1,2,2};
int larray[6] = {1,1,1,1,1,2}
Now I need to check if vector and array have got the same elements. I can't modify the vector and the array, but I can create a new container and copy the element from vector and array to this new container and then copare them. I am asking about this, because I would like to do this in en efficient way. Thanks.
That's a variant of what proposed by soon:
#include <iostream>
#include <unordered_set>
#include <vector>
int main()
{
std::vector<int> v{5, 7, 3, 1, 2, 7};
int arr[] = {3, 5, 1, 7, 2, 7};
std::vector<int> mv(std::begin(v), std::end(v));
std::vector<int> ma(std::begin(arr), std::end(arr));
std::sort(mv.begin(), mv.end()) ;
std::sort(ma.begin(), ma.end()) ;
std::cout << "Are equal? " << (mv == ma) << std::endl;
return 0;
}
There are a lot of different ways of solving this problem, each has proc and cons.
Some pre-tests
Obviously, two ranges cannot be equal, if they have different size.
You could calculate an order independent hash function for elements in the ranges (thanks, #Michael Anderson). It could be a sum of elements, or you just could xor them all. Arrays with different hash value cannot be equal.
std::unordered_multiset
You could create an unordered_multiset, which holds frequency of elements in the range. While it has linear complexity in average, it may be O(n^2) because of hash collisions. Quote from the Standard (N3337, § 23.5.7.2):
Complexity: Average case linear, worst case quadratic.
However, you should also remember the complexity of std::unordered_set::operator==:
For unordered_set and unordered_map, the complexity of
operator== (i.e., the number of calls to the == operator of the
value_type, to the predicate returned by key_equal(), and to the
hasher returned by hash_function()) is proportional to N in the
average case and to N^2 in the worst case, where N is a.size().
For unordered_multiset and unordered_multimap, the complexity of
operator== is proportional to sum of Ei^2 in the average case and
to N^2 in the worst case, where N is a.size(), and Ei is the
size of the ith equivalent-key group in a.
However, if the
respective elements of each corresponding pair of equivalent-key
groups Eai and Ebi are arranged in the same order (as is commonly
the case, e.g., if a and b are unmodified copies of the same
container), then the average-case complexity for unordered_multiset
and unordered_multimap becomes proportional to N (but worst-case
complexity remains O(N2), e.g., for a pathologically bad hash
function).
Example:
#include <iostream>
#include <unordered_set>
#include <vector>
int main()
{
std::vector<int> v{5, 7, 3, 1, 2, 7};
int arr[] = {3, 5, 1, 7, 2, 7};
std::unordered_multiset<int> mv(std::begin(v), std::end(v));
std::unordered_multiset<int> ma(std::begin(arr), std::end(arr));
std::cout << "Are equal? " << (mv == ma) << std::endl;
return 0;
}
std::sort
You could compare sorted copies of your range. According to the Standard (N3337, § 25.4.1.1) , it has O(n * log(n)) complexity:
Complexity: O(N log(N)) (where N == last - first) comparisons.
Example:
#include <iostream>
#include <algorithm>
#include <vector>
int main()
{
std::vector<int> v{5, 7, 3, 1, 2, 7};
int arr[] = {3, 5, 1, 7, 2, 7};
std::vector<int> sv(v);
std::vector<int> sa(std::begin(arr), std::end(arr));
std::sort(std::begin(sv), std::end(sv));
std::sort(std::begin(sa), std::end(sa));
std::cout << "Are equal? " << (sv == sa) << std::endl;
return 0;
}
Here is template function to compare vector with array:
#include <array>
#include <algorithm>
#include <vector>
template <class T, std::size_t N>
bool equal(const std::vector<T>& v, const std::array<T, N>& a)
{
if (v.size() != N)
return false;
return std::equal(v.begin(), v.end(), a.begin());
}
Usage example:
std::vector<int> v = {1, 2, 3};
std::array<int, 4> a = {1, 2, 3, 4};
bool eq = equal(v, a);
At first convert the array into v1 vector.
v={1,1,2,3,4}; vector and
v1={1,1,2,3,4}; converted from array
bool f=0;
if(equal(v.begin(),v.end(),v1.begin())) //compare two vector, if equal return true
{
f=1;
}
}
if(f==1)
cout<<"Yes"<<endl;
else cout<<"No"<<endl;
I have the vector that defines the order of items (0..N-1), e.g.
{5, 0, 4, 3, 2, 1, 7, 6}.
I have to sort subsets of that vector. So, for {0, 1, 2, 5} I should get {5, 0, 2, 1}.
I tested the following solutions:
Create a set of items in a subset, then clear the subset, go through the ordering vector, adding only items in the set.
Create new sorted vector by going through the ordering vector, adding only items found by in the subset by std::lower_bound.
The second solution seems much faster, although it needs subset to be sorted. Are there any better solutions? I am using C++/STL/Qt, but the problem is probably not language-dependent.
Check this code :-
#include <iostream>
#include <algorithm>
#include <vector>
struct cmp_subset
{
std::vector<int> vorder;
cmp_subset(const std::vector<int>& order)
{
vorder.resize(order.size());
for (int i=0; i<order.size(); ++i)
vorder.at(order[i]) = i;
}
bool operator()(int lhs, int rhs) const
{
return vorder[lhs] < vorder[rhs];
}
};
int main()
{
std::vector<int> order = {5, 0, 4, 3, 2, 1, 7, 6};
std::vector<int> subset = {0, 1, 2, 5};
for (auto x : subset)
std::cout << x << ' ';
std::cout << '\n';
std::sort(subset.begin(), subset.end(), cmp_subset(order));
for (auto x : subset)
std::cout << x << ' ';
std::cout << '\n';
return 0;
}
The code is copied from here