我正在尝试自学(重新学习)C ++并通过在线书籍和测试来解决问题以获得一些练习。我遇到了这个让我有点困惑的问题。我最好怎么做呢?
我必须写一个函数
class Solution { public int distinct (int [] A); }
返回数组A中不同值的数量。 我可以假设数组范围是0到100,000。并且元素都是+或 - 1,000,000的整数。 有任何想法吗?我正在考虑循环并计算每个值,但这可能效率非常低吗?提前谢谢。
答案 0 :(得分:6)
修改更新:包含空间优化算法以及娱乐
您可以使用std :: set来包含唯一值。只需将数组元素复制到一个集合中(无论如何你喜欢),然后计算集合中唯一元素的数量。
这是一段相当简洁的代码,它甚至不需要你指定数组的大小(不过,通常在c ++中你仍然使用std::vector
):
在http://ideone.com/rpWGS 上查看(包含测试数据和输出)
#include <set>
class Solution
{
public:
// using std::set (max O(n) additional storage)
template<size_t N>
static size_t distinct (int (&a)[N])
{
return std::set<int>(a, a+N).size();
}
// using std::unique (inplace mutation; no additional storage)
template<size_t N>
static size_t distinct_optim(int (&a)[N])
{
std::sort(a, a+N);
int* newend = std::unique(a, a+N);
return newend - a;
}
};
答案 1 :(得分:6)
您的解决方案相当有效(实际上,就时间复杂度而言,尽可能高效),但在空间中 - 要计算值,您需要一个大小与可能值范围相对应的数组,因此,计算100,000个项目数组中的实例,需要一个约2,000,000个项目的辅助数组(范围从-1,000,000到1,000,000)。
您有两种方法可以避免/减少这种情况。一种是为每个可能的输入存储一位,并在看到该输入时设置该位。这具有相同的基本复杂度,但是将计数空间减少到必要的最小值(即,您并不关心任何输入发生了多少次,只是它是否发生)。在C ++中,显而易见的方法是std::vector<bool>
。虽然经常受到诽谤,但在这种情况下,vector<bool>
完全符合您的要求。
另一种可能性是使用从输入数到计数/位的稀疏映射。特别是当您的范围远大于输入数量时,这可以节省相当多的空间(所占用的空间将与输入数量成比例,而不是范围)。在C ++中,显而易见的方法是std::set<int>
。为了保持相同的预期复杂度(O(N)而不是O(N log N),您需要使用unordered_set
代替。
另一种可能性是对输入进行排序,然后消除重复。这通常使辅助存储器保持最小,但通常需要稍长的时间来执行(O(N log N)而不是O(N))。为此,您可能会使用std::vector
,std::sort
和std::unique
。
答案 2 :(得分:2)
对数组A进行排序 然后遍历排序的数组并计算两个连续数字之间的差异非零的次数。 确保您处理数组的边缘以及数组大小为1的情况。
答案 3 :(得分:1)
我可以想到两个选择:
1)使用快速排序或合并排序对矢量进行排序,然后迭代排序后的矢量,每次遇到与当前值不同的值时计数。
2)设置大小为1,000,000的std::vector<bool>
,并在迭代数组时输入true
值。之后,您计算true
值的数量。我说vector<bool>
因为它针对高效存储进行了优化,即它可能在一个字节中存储8个bool。
答案 4 :(得分:1)
为了获得数组中不同值的数量,我可以看到两种可能性。
首先是对它们进行排序,然后计算转换次数(加1)。例如,以下列表:
1 1 1 1 2 2 3 4 4 5
^ ^ ^ ^
有四个转换,因此有五个distint值。
另一种可能性是建立一个“布尔”数组,表明之前是否有过一个数字,伪代码如(在你的情况下):
def countDistinct (array):
def notSeenYet[-1,000,000..1,000,000] as all true
count = 0
for each value in array:
if notSeenYet[value]:
notSeenYet[value] = false
count = count + 1
return count
第一种要求排序最多为O(n log n)时间复杂度。对于100,000个元素,这不太可能是一个严重的问题,但您可能不希望以任何方式修改数组(这需要复制,O(n)空间复杂度)。
第二个是O(n)时间复杂度和持续存储的情况。两百万个布尔值可能值得关注,具体取决于您的环境,但是,如果它可用,那就更好了,假设时间是您的主要关注点(通常是)。