返回一个数组,该数组包含的数组中的元素数量小于或等于给定数组中的元素的数量

时间:2019-06-24 10:46:31

标签: c++ algorithm hashmap complexity-theory binary-search

我遇到了这个问题,想知道是否有更好的解决方案。

例如

  • 数组a = [1,4,2,4]
  • 数组b = [3,5]

期望的输出 ==> [2,4]

编辑:再举一个例子

  • 数组a = [1,4,2,4]
  • 数组b = [3,1000000]

期望的输出 ==> [2,4]

到目前为止,我发现并尝试过的运行在O(nlogn)+ O(blogn)和O(n)中。

O(nlogn)+ O(blogn)方法:

 int binarysearch(vector<int>arr, int l, int r, int target) 
 {
      int mid;
      while(l <= r)
      {
          mid = (r+l) / 2;

          if(arr[mid] > target)
              r = mid - 1;
          else
              l = mid + 1;
      }

      return r; 
 }

vector<int> counts(vector<int> a, vector<int> b)
{
    vector<int> result;
    sort(a.begin(), a.end()); // O(nlogn)

    for(auto i : b){
        int count = binarysearch(a, 0, a.size()-1, b); // b*O(log n) times
        result.push_back(count)
    }
    return result;
}

O(n)方法:

vector<int> counts(vector<int> a, vector<int> b)
{
    vector<int> result;
    int maxi = *max_element(b.begin(), b.end()) + 1;
    int mymap[maxi] = {0};

    for(auto i : a) mymap[i]++;

    for(int i = 1; i < maxi; i++){
        mymap[i] = mymap[i] + mymap[i-1];
    }

    for(auto i : b){
        result.push_back(mymap[i]);
    }
    return result;
}

5 个答案:

答案 0 :(得分:1)

  

[我]在想是否有更好的复杂度来解决问题。

     

时间复杂度。

     

O(n)方法:

不,没有比线性时间复杂度低的解决方案。

也就是说,您的线性解是错误的。如果输入数组包含1000000或更大的值或负数,则访问mymap的边界之外,并且行为未定义。此外,i <= 1000000还在上次迭代的边界之外访问mymap。此外,int[1000000]太大而不能成为局部变量。在某些系统上,即使是这样的变量也可能导致堆栈溢出。

答案 1 :(得分:1)

没有比O(n)更好的方法了。

所以这也是O(n),但改编了STL样式:

template <class Iter1, class Iter2>
std::vector<std::size_t> counts(const Iter1 beg_a, const Iter1 end_a, const Iter2 beg_b, const Iter2 end_b)
{
    std::vector<std::size_t> result;
    const auto& max = *std::max_element(beg_b, end_b);
    std::vector<std::size_t> mymap(max + 1, 0);
    for (auto iter = beg_a; iter != end_a; iter++)
    {
        if (*iter <= max)
        {
            mymap[*iter]++;
        }
    }
    for (std::size_t i = 1; i < mymap.size(); i++)
    {
        mymap[i] = mymap[i] + mymap[i - 1];
    }
    for (auto iter = beg_b; iter != end_b; iter++)
    {
        result.push_back(mymap[*iter]);
    }
    return result;
}

答案 2 :(得分:0)

好吧,事实证明,有一种更快的方法来计算地图索引。例如给定a = {1,4,2,4,5,8,80}和b = {3,1000000}。 所需输出为[2,7]。

使用我以前的方法,我需要计算mymap [4],mymap [5] .. mymap [9999] .... mymap [1000000]。这就是程序崩溃并返回运行时错误的原因。

我们处理此问题的方法是使用for(auto&entry:mymap),它可以访问所有字典/地图。然后,我们使用upper_bound STL C ++返回正确的映射。

    vector<int> counts(vector<int> nums, vector<int> maxes){


    vector<int> result;

    map<int,unsigned int> mymap;
    for(auto i : nums) mymap[i]++;

    // doesn't need to run 1000000 times
    int temp = 0;
    for(auto& entry: mymap){
        entry.second = entry.second + temp;
        temp = entry.second;
        //cout << "first : " << entry.first << "second: " << entry.second << endl;
    }

    map<int,unsigned int>::iterator itl;
    for(auto i : maxes){
        itl = --mymap.upper_bound(i); // points to the correct map
        result.push_back(itl->second);
    }

    return result;
 }

答案 3 :(得分:0)

首先让我们采用更好的表示法:让我们称A为a中元素的数量,B为B中元素的数量,并说元素为M位值。 正如其他人所说,您的解决方案是A log(A)来构建映射,再加上B log(A)来获取返回的值。

使用https://en.wikipedia.org/wiki/Y-fast_trie可以得到(A+B) log M,如果使用A >> M,则速度更快(但在大多数情况下,实践中可能会更慢)。

答案 4 :(得分:-1)

希望这对您有所帮助。

    private List<Integer> compareAndCount (@NotNull List<Integer> integerListA, @NotNull List<Integer> integerListB){
    List<Integer> countedIntList = new ArrayList<>();
    int counter;

    for (int B : integerListB ){
        counter = 0;
        for (int A : integerListA){
            if(A < B){
                counter++;
            }
        }
        countedIntList.add(counter);
    }
    return countedIntList;
}