这是另一种解决方案,使用 STL 算法函数:
#include <iostream>
#include <algorithm>
#include <numeric>
using namespace std;
bool g(int *t, int n)
{
if ( n == 0 )
return false;
std::sort(t, t + n);
return (t[0] == 1) && // first number must be 1
(std::distance(t, std::unique(t, t + n)) == n) && // all must be unique
(std::accumulate(t, t + n, 0) == (n * (n + 1)) / 2); // has to add up correctly
}
int main()
{
int arr[] = {1,2,3,4,5,6,7};
std::cout << g(arr, 7);
}
Live Example
对数字列表排序后,std::unique算法函数用于将非唯一项移动到数组的末尾,然后给我们一个指向该非唯一项序列开始的指针。如果所有值都是唯一的,则std::unique 将返回数组末尾之后的一个位置。
这就是std::distance 的原因——它告诉我们非唯一序列的开头和开头之间的数字数量是否等于整个列表中的数字数量。
std::accumulate 只是简单地将序列中的所有数字相加,看看结果是否为(n * (n+1)) / 2,这是求第一个n 连续整数(从1 开始)之和的经典公式。
这是一个更短的解决方案:
#include <iostream>
#include <algorithm>
using namespace std;
bool g(int *t, int n)
{
if ( n == 0 )
return false;
std::sort(t, t + n);
return (t[0] == 1) && // first number must be 1
(t[n-1] == n) && // last must be n
(std::distance(t, std::unique(t, t + n)) == n); // all must be unique
}
另一种方法:
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
bool g(int *t, int n)
{
if ( n == 0 )
return false;
std::sort(t, t + n);
return (t[0] == 1) && // first number must be 1
(t[n-1] == n) && // last must be n
(std::set<int>(t, t+n).size() == n); // all must be unique
}
int main()
{
int arr[] = {1,2,3,4,5,6,7};
std::cout << g(arr, 7);
}
Live Example
在这种方法中,会从号码列表中创建一个临时的std::set。由于std::set只存储唯一的数字,所以插入所有项目后集合的size()必须等于n才能确定所有数字是否唯一。