Skip to content

Commit

Permalink
⭐ Add is_permutation.
Browse files Browse the repository at this point in the history
  • Loading branch information
Alinshans committed Aug 9, 2017
1 parent 55a1c7d commit c48f6a3
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 1 deletion.
94 changes: 94 additions & 0 deletions MyTinySTL/algo.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "heap_algo.h"
#include "iterator.h"
#include "tempbuf.h"
#include "functional.h"

namespace mystl
{
Expand Down Expand Up @@ -1594,6 +1595,99 @@ rotate_copy(ForwardIterator first, ForwardIterator middle,
return mystl::copy(first, middle, mystl::copy(middle, last, result));
}

/*****************************************************************************************/
// is_permutation
// 判断[first1,last1)是否为[first2, last2]的排列组合
/*****************************************************************************************/
template <class ForwardIter1, class ForwardIter2, class BinaryPred>
bool is_permutation_aux(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2, ForwardIter2 last2,
BinaryPred pred)
{
constexpr bool is_ra_it = mystl::__is_random_access_iterator<ForwardIter1>::value
&& mystl::__is_random_access_iterator<ForwardIter2>::value;
if (is_ra_it)
{
auto len1 = last1 - first1;
auto len2 = last2 - first2;
if (len1 != len2)
return false;
}

// 先找出相同的前缀段
for (; first1 != last1 && first2 != last2; ++first1, (void) ++first2)
{
if (!pred(*first1, *first2))
break;
}
if (is_ra_it)
{
if (first1 == last1)
return true;
}
else
{
auto len1 = mystl::distance(first1, last1);
auto len2 = mystl::distance(first2, last2);
if (len1 == 0 && len2 == 0)
return true;
if (len1 != len2)
return false;
}

// 判断剩余部分
for (auto i = first1; i != last1; ++i)
{
for (auto j = first1; j != i; ++j)
if (pred(*j, *i))
goto next_loop; // 相同元素已经计算过了

// 计算 *i 在 [first2, last2) 的数目
auto c2 = 0;
for (auto j = first2; j != last2; ++j)
{
if (pred(*i, *j))
++c2;
}
if (c2 == 0)
return false;

// 计算 *i 在 [first1, last1) 的数目
auto c1 = 1;
auto j = i;
for (++j; j != last1; ++j)
{
if (pred(*i, *j))
++c1;
}
if (c1 != c2)
return false;
next_loop:
;
}
return true;
}

template <class ForwardIter1, class ForwardIter2>
bool is_permutation(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2, ForwardIter2 last2)
{
typedef typename iterator_traits<ForwardIter1>::value_type v1;
typedef typename iterator_traits<ForwardIter2>::value_type v2;
static_assert(std::is_same<v1, v2>::value,
"the type should be same in mystl::is_permutation");
return is_permutation_aux(first1, last1, first2, last2,
mystl::equal_to<v1>());
}

template <class ForwardIter1, class ForwardIter2, class BinaryPred>
bool is_permutation(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2, ForwardIter2 last2,
BinaryPred pred)
{
return is_permutation_aux(first1, last1, first2, last2, pred);
}

/*****************************************************************************************/
// next_permutation
// 取得[first, last)所标示序列的下一个排列组合,如果没有下一个排序组合,返回 false,否则返回 true
Expand Down
14 changes: 13 additions & 1 deletion Test/algorithm_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ bool cmp(const int& a, const int& b) { return b < a; }
int unary_op(const int& x) { return x + 1; }
int binary_op(const int& x, const int& y) { return x + y; }

// 以下为 79 个函数的简单测试
// 以下为 80 个函数的简单测试

// algobase test:
TEST(copy_test)
{
Expand Down Expand Up @@ -713,6 +714,17 @@ TEST(min_elememt_test)
mystl::max_element(arr2, arr2 + 6, std::less<double>()));
}

TEST(is_permutation_test)
{
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 3,4,5,2,1 };
int arr3[] = { 1,2,3,4,6 };
EXPECT_EQ(std::is_permutation(arr1, arr1 + 5, arr2, arr2 + 5),
mystl::is_permutation(arr1, arr1 + 5, arr2, arr2 + 5));
EXPECT_EQ(std::is_permutation(arr1, arr1 + 5, arr3, arr3 + 5),
mystl::is_permutation(arr1, arr1 + 5, arr3, arr3 + 5));
}

TEST(next_permutation_test)
{
int arr1[] = { 1,2,3,3 };
Expand Down

0 comments on commit c48f6a3

Please sign in to comment.