【问题标题】:Modify sorted array or sort the array everytime?修改排序数组或每次排序数组?
【发布时间】:2017-05-04 06:01:04
【问题描述】:

问题:给定一个大小为 N 的数组,打印具有连续元素的大小为 K 的已排序子集。

N = 10, K = 4 
8 4 7 5 1 10 3 9 2 6
Output:
4 5 7 8, 1 4 5 7, 1 5 7 10, 1 3 5 10, ...

方法1:对所有子集进行排序并打印。

复杂性分析:

复制K个元素:O((N - K + 1) * (K)) //子集的数量*子集的大小

排序子集:使用STL,排序子集的最坏情况时间是O(K log K)。

因此,O((N - K + 1) * (K) + (N - K + 1) * (K log K))

方法 2:从输出序列来看,连续子集相差 2 个元素。因此对于第二个子集,删除第一个元素,在正确的位置插入第K+1个元素。

复杂性分析:

创建第一个子集:K

删除和插入 - 线性搜索(是否应该优化!):K

因此,O(K + (N - K + 1) * (K))

我想知道第二种方法是否更快?有显着的收获吗?是否值得不使用 STL 实现?这可以进一步改善吗?还有其他方法吗?以及对 STL 容器实施的任何建议。

【问题讨论】:

  • 第二种方法,你可以使用二分查找,虽然插入和删除仍然需要O(k)时间

标签: c++ algorithm sorting stl


【解决方案1】:

是否允许重复?

如果不允许重复,则使用std::set,否则使用std::multisetsetmultiset 将始终保持您的元素排序,并且每次插入都将进入正确的有序位置。您不必担心何时对它们进行排序。

在插入期间对所有内容进行排序实际上更便宜,因为当您必须进行搜索时,您不必与所有元素进行比较,而只需与其中的一部分进行比较。

【讨论】:

    【解决方案2】:

    使用std::multiset。它会简单而干净:

    vector<int> v = input();
    multiset<int> s;
    for (int i = 0; i < k; ++i) {
        s.insert(v[i]);
    }
    print_set(s);
    
    for (int i = 0; i < n-k; ++i) {
        s.erase(s.find(v[i]));
        s.insert(v[i+k]);
    
        cout << ",";
        print_set(s);
    }
    

    你可以试试:http://ideone.com/moD3bg

    所有操作的复杂度都是 O(nlogk)。但是不要记得打印所有这些数据的复杂度是 O(n*k)。

    【讨论】:

    • 但是为什么你使用 find 如果你可以直接传递值来擦除 multiset 的成员函数
    • @Kapil 因为如果允许重复,按值擦除可能会从多重集中删除多个数字
    【解决方案3】:

    解决这个问题的另一种方法:

      int k=4;
      std::vector<int> v = {8,4,7,5,1,10,3,9,2,6};
      std::multiset<int> ss;
      for(auto itr=v.begin();itr<v.end();itr++)
      {
        size_t remaining(std::distance(itr+k, v.end())); 
        std::cout<<remaining<<std::endl;
        ss.insert(itr,itr+k);
        print_set(ss);
        if(remaining==0)
          break;
        ss.clear();
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-10
      • 1970-01-01
      • 1970-01-01
      • 2013-08-26
      • 1970-01-01
      • 1970-01-01
      • 2021-03-09
      相关资源
      最近更新 更多