patterncppMinor
Is_permutation() on sequence containers in O(n) complexity - follow-up
Viewed 0 times
sequenceis_permutationfollowcontainerscomplexity
Problem
This question is a continuation of my previous question:
Check is_permutation on a pair of same sized arrays.
I improved the implementation to generalize for all sequence containers. Please let me know how I can improve this implementation again.
```
#include
#include
#include
#include
#include
template
std::unordered_map count_frequency( T1 first, T1 last )
{
std::unordered_map temp_unordered_map;
auto temp_unordered_map_end = std::end( temp_unordered_map );
while( first != last )
{
auto it_temp_unordered_map = temp_unordered_map.find( *first );
if( it_temp_unordered_map == temp_unordered_map_end )
{
temp_unordered_map.emplace( *first, 1 );
}
else
{
++( it_temp_unordered_map->second );
}
++first;
}
return temp_unordered_map;
}
template
bool is_permutation( const T1 first1, const T1 last1, const T2 first2, const T2 last2 )
{
if( std::distance( first1, last1 ) != std::distance( first2, last2 ) )
{
return false;
}
std::unordered_map first_map = count_frequency( first1, last1 );
std::unordered_map second_map = count_frequency( first2, last2 );
std::pair::iterator,std::unordered_map::iterator > myPair=
std::mismatch( std::begin( first_map ), std::end( first_map ), std::begin( second_map ),
[]( std::pair& seed1, std::pair & seed2)
{ return seed1.second == seed2.second; }
);
return myPair.first == first_map.end() && myPair.second == second_map.end();
}
int main()
{
const std::array array1 { { 1, 3, 2, 4, 5 } };
const std::array array2 { { 1, 2, 4, 3 } };
if( ::is_permutation( std::begin( array1 ), std::end( array1 ), std::begin( array2 ), std::end( array2 ) ) )
{
std::cout vec1 { { 1, 3, 2, 4 } };
const std::vector vec2 { { 1, 2, 4, 3 } };
if( ::is_permutation( std::begin( vec1 ), std::end( vec1 ), std::begi
Check is_permutation on a pair of same sized arrays.
I improved the implementation to generalize for all sequence containers. Please let me know how I can improve this implementation again.
```
#include
#include
#include
#include
#include
template
std::unordered_map count_frequency( T1 first, T1 last )
{
std::unordered_map temp_unordered_map;
auto temp_unordered_map_end = std::end( temp_unordered_map );
while( first != last )
{
auto it_temp_unordered_map = temp_unordered_map.find( *first );
if( it_temp_unordered_map == temp_unordered_map_end )
{
temp_unordered_map.emplace( *first, 1 );
}
else
{
++( it_temp_unordered_map->second );
}
++first;
}
return temp_unordered_map;
}
template
bool is_permutation( const T1 first1, const T1 last1, const T2 first2, const T2 last2 )
{
if( std::distance( first1, last1 ) != std::distance( first2, last2 ) )
{
return false;
}
std::unordered_map first_map = count_frequency( first1, last1 );
std::unordered_map second_map = count_frequency( first2, last2 );
std::pair::iterator,std::unordered_map::iterator > myPair=
std::mismatch( std::begin( first_map ), std::end( first_map ), std::begin( second_map ),
[]( std::pair& seed1, std::pair & seed2)
{ return seed1.second == seed2.second; }
);
return myPair.first == first_map.end() && myPair.second == second_map.end();
}
int main()
{
const std::array array1 { { 1, 3, 2, 4, 5 } };
const std::array array2 { { 1, 2, 4, 3 } };
if( ::is_permutation( std::begin( array1 ), std::end( array1 ), std::begin( array2 ), std::end( array2 ) ) )
{
std::cout vec1 { { 1, 3, 2, 4 } };
const std::vector vec2 { { 1, 2, 4, 3 } };
if( ::is_permutation( std::begin( vec1 ), std::end( vec1 ), std::begi
Solution
I would initially agree that the complexity of your solution is O(n), though, there are extreme cases where the performance of your
Note that you have a very complicated equality-check comparing your two frequency-maps.... you have:
as far as I can tell, the size-check is redundant, and the rest can be simply:
I put your code in this ideone, and the replacement code in this ideone here.
count_frequency could be greater - unordered_map.emplace() is 'average case constant time, worst case linear', I don't believe a worst-case situation would happen for you.Note that you have a very complicated equality-check comparing your two frequency-maps.... you have:
if( std::distance( first1, last1 ) != std::distance( first2, last2 ) )
{
return false;
}
std::unordered_map first_map = count_frequency( first1, last1 );
std::unordered_map second_map = count_frequency( first2, last2 );
std::pair::iterator,std::unordered_map::iterator > myPair=
std::mismatch( std::begin( first_map ), std::end( first_map ), std::begin( second_map ),
[]( std::pair& seed1, std::pair & seed2)
{ return seed1.second == seed2.second; }
);
return myPair.first == first_map.end() && myPair.second == second_map.end();as far as I can tell, the size-check is redundant, and the rest can be simply:
template
bool is_permutation( const T1 first1, const T1 last1, const T2 first2, const T2 last2 )
{
return count_frequency( first1, last1 ) == count_frequency( first2, last2 );
}I put your code in this ideone, and the replacement code in this ideone here.
Code Snippets
if( std::distance( first1, last1 ) != std::distance( first2, last2 ) )
{
return false;
}
std::unordered_map< int, int > first_map = count_frequency( first1, last1 );
std::unordered_map< int, int > second_map = count_frequency( first2, last2 );
std::pair<std::unordered_map< int, int >::iterator,std::unordered_map< int, int >::iterator > myPair=
std::mismatch( std::begin( first_map ), std::end( first_map ), std::begin( second_map ),
[]( std::pair< const int, int >& seed1, std::pair< const int, int > & seed2)
{ return seed1.second == seed2.second; }
);
return myPair.first == first_map.end() && myPair.second == second_map.end();template < typename T1, typename T2 >
bool is_permutation( const T1 first1, const T1 last1, const T2 first2, const T2 last2 )
{
return count_frequency( first1, last1 ) == count_frequency( first2, last2 );
}Context
StackExchange Code Review Q#86241, answer score: 3
Revisions (0)
No revisions yet.