📜  排序一个递增-递减数组

📅  最后修改于: 2021-04-22 01:52:08             🧑  作者: Mango

给定K增减数组arr [] ,任务是对给定数组进行排序。如果元素重复增加到某个索引,然后减少,然后又增加,总共K次,则数组被称为K递增-递减。下图显示了4增减数组。

例子:

方法:蛮力方法是在不利用k增加-减少属性的情况下对数组进行排序。此方法的时间复杂度为O(n logn),其中n是数组的长度。

如果k显着小于n,则可以找到一种更好的方法,并且时间复杂度更低。例如,如果k = 2,则输入数组由两个子数组组成,一个子数组增加,另一个子数组减少。反转第二个子数组会产生两个排序的数组,然后合并结果,可以在O(n)时间内完成。概括而言,我们可以首先反转每个递减子数组的顺序。例如,在上图中,该数组可以分解为四个分类的数组,分别为{57,131,493},{221,294},{339,418,458}和{190,442}。现在,可以使用最小堆技术合并这些排序的数组。

下面是上述方法的实现:

// C++ implementation of the approach
#include 
using namespace std;
  
// A pair of pairs, first element is going to
// store value, second element index of array
// and third element index in the array
typedef pair > ppi;
  
// This function takes an array of arrays as an
// argument and all arrays are assumed to be
// sorted
// It merges them together and returns the
// final sorted output
vector mergeKArrays(vector > arr)
{
    vector output;
  
    // Create a min heap with k heap nodes
    // Every heap node has first element of an array
    priority_queue, greater > pq;
  
    for (int i = 0; i < arr.size(); i++)
        pq.push({ arr[i][0], { i, 0 } });
  
    // Now one by one get the minimum element
    // from min heap and replace it with next
    // element of its array
    while (pq.empty() == false) {
        ppi curr = pq.top();
        pq.pop();
  
        // i ==> Array Number
        // j ==> Index in the array number
        int i = curr.second.first;
        int j = curr.second.second;
  
        output.push_back(curr.first);
  
        // The next element belongs to same array as
        // current
        if (j + 1 < arr[i].size())
            pq.push({ arr[i][j + 1], { i, j + 1 } });
    }
  
    return output;
}
  
// Function to sort the alternating
// increasing-decreasing array
vector SortKIncDec(const vector& A)
{
    // Decompose the array into a
    // set of sorted arrays
    vector > sorted_subarrays;
    typedef enum { INCREASING,
                   DECREASING } SubarrayType;
    SubarrayType subarray_type = INCREASING;
    int start_idx = 0;
    for (int i = 0; i <= A.size(); i++) {
  
        // If the current subarrays ends here
        if (i == A.size()
            || (A[i - 1] < A[i]
                && subarray_type == DECREASING)
            || (A[i - 1] >= A[i]
                && subarray_type == INCREASING)) {
  
            // If the subarray is increasing
            // then add from the start
            if (subarray_type == INCREASING) {
                sorted_subarrays.emplace_back(A.cbegin() + start_idx,
                                              A.cbegin() + i);
            }
  
            // If the subarray is decreasing
            // then add from the end
            else {
                sorted_subarrays.emplace_back(A.crbegin()
                                                  + A.size() - i,
                                              A.crbegin()
                                                  + A.size()
                                                  - start_idx);
            }
            start_idx = i;
            subarray_type = (subarray_type == INCREASING
                                 ? DECREASING
                                 : INCREASING);
        }
    }
  
    // Merge the k sorted arrays`
    return mergeKArrays(sorted_subarrays);
}
  
// Driver code
int main()
{
    vector arr = { 57, 131, 493, 294, 221,
                        339, 418, 458, 442, 190 };
  
    // Get the sorted array
    vector ans = SortKIncDec(arr);
  
    // Print the sorted array
    for (int i = 0; i < ans.size(); i++)
        cout << ans[i] << " ";
  
    return 0;
}
输出:
57 131 190 221 294 339 418 442 458 493

时间复杂度: O(n * logk),其中n是数组的长度。