计算数组中不同整数的数量

时间:2015-08-14 21:04:46

标签: c++ algorithm

为了找到从lr索引的数组中不同数字的数量,我编写了一个代码块,如:

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';

解释 对于数组说,a = 5 6 1 1 3 2 5 7 1 2十个元素。如果我们想检查[1]和[8]之间的第二个和第九个元素(包括两者)之间的不同数字的数量,我试图实现的逻辑将首先取count = 8(元素数量)被认为是)然后它从6的[1]开始并检查其后的任何其他6,如果它确实找到,它将计数减1并继续行中的下一个数字。因此,如果在那之后再出现6,则不会包含两次。

问题我尝试过小型测试用例,但是有效。但是当我尝试使用更大的数据时,它不起作用,所以我想知道我的逻辑会在哪里失败?

更大的数据,如与程序的其他部分集成然后使用。哪个输出不正确

7 个答案:

答案 0 :(得分:4)

您可以尝试使用std::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;
}

答案 1 :(得分:2)

这是一个不使用std::set的答案,尽管该解决方案可能更简单。

#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
}

如果你进入那里,那就是live on Coliru

-

编辑:此处,还有一个简短版本的解决方案。

#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();
}

答案 2 :(得分:2)

要问这类问题的第一个问题是值的可能范围是多少。如果数字范围 override func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent?) { if motion == .MotionShake{ let randomNumber = arc4random_uniform(2) + 1 print(randomNumber) if randomNumber == 1 { labelOne.text = "Sorry!" labelTwo.text = "You Have Not Won This Time" labelThree.text = "Better Luck Tomorrow" } if randomNumber == 2 { labelOne.text = "Winner!" labelTwo.text = "1 x Shot Patron Cafe" labelThree.text = "Show at the bar to claim." } let xPosition = stampView.frame.origin.x //View will slide 20px up let yPosition = stampView.frame.origin.y - 100 let height = stampView.frame.size.height let width = stampView.frame.size.width UIView.animateWithDuration(3.0, animations: { self.stampView.frame = CGRectMake(xPosition, yPosition, height, width) }) print("SHAKEN!") } } 是&#34;相当小&#34;,则可以使用大小为N的布尔数组来指示是否存在与索引对应的数字。您从N迭代到l,设置标志,如果标志尚未设置,则递增计数器。

r

就复杂性而言,这种方法和基于集合的方法都是O(n),但是这种方法更快,因为不涉及散列。对于较小的count = 0; for(int i=l; i<=r; i++) { if (! isthere[arr[i]]) { count++; isthere[arr[i]] = TRUE; } } ,例如0到255之间的数字,很可能这也可能是内存密集度较低。对于较大的N,例如,如果允许任何32位整数,则基于集合的方法更合适。

答案 3 :(得分:1)

你说你不介意另一个解决方案。所以这就是。它使用set - 一种只存储唯一元素的结构。顺便说一句,在更大的数据上 - 它将比具有两个周期的解决方案快得多。

FroslagOpslag

答案 4 :(得分:1)

在下面的过程中,我给出了计算唯一数字的过程。在这种技术中,您只需在数组中获得唯一元素。此过程将使用垃圾值更新您的数组。所以在这个过程中你不能再使用这个数组(我们将使用)。此数组将使用不同的元素自动调整大小。

#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;
}

如果你想解决这个问题(我之前说过),你可以按照这个过程。你可以通过在另一个数组中处理你的数组来处理这个问题。

#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;
}

答案 5 :(得分:0)

就个人而言,我只是使用标准算法

mainPage

这显然依赖于允许修改数组(任何重复项都移动到#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'; } 的末尾)。但是如果需要的话,可以很容易地创建一个数组的副本并在副本上工作。

答案 6 :(得分:0)

TL; DR:使用此:

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();
}

有两种方法:

  1. 将所有内容插入集合,对集合计数。因为您不关心顺序,所以可以使用比std::unordered_set更快的std::setstd::set被实现为执行大量分配的树,因此它可能很慢。

  2. 使用std::sort。如果要保留原始数组,则需要对其进行复制。

这是一个完整的例子。

#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";
}

在排序版本中使用该循环应该比std::unique快。

2的复杂度比1差。-平均情况为O(N)vs O(N log N)。但是它避免了分配,因此对于较小的数组或已排序或大部分已排序的数组,最终可能会更快。

您绝对应该使用std::set,并且可能不使用std::unique(尽管这样做确实会导致更少的代码行,并且对性能取决于您)。

无论如何,在大多数情况下,您应该使用设置的版本-它更简单,并且在几乎所有情况下都应该更快。

  1. 正如其他人所提到的,如果您知道输入域很小,则可以使用bool数组而不是unordered_set