交换后排序检查

时间:2017-11-27 18:09:18

标签: algorithm sorting c++11

所以我在一项任务中遇到了问题。

你已经给出了数字序列和n个操作,每个都有两个数字(这个给定序列中的索引)。

您必须检查每个操作后的序列是否排序。 (每个操作都适用)。

我的问题是我的解决方案太慢了。它适用于O(n ^ 2)。 (我只是在c ++ 11中进行交换和使用is_sorted)。如何让它更快?

提前致谢

1 个答案:

答案 0 :(得分:1)

我认为你所说的是你有一个序列,比如......

3, 9, 34, 8, 5, 25, 10

和交换两个数字的操作,因此交换[2,4](当然为零索引)将产生

3, 9, 5, 8, 34, 25, 10

即使操作没有交换,而是执行仅对这两个数字起作用的其他操作,该算法也可以工作;事实上,这适用于任何改变该数组中任何数字的内容:

首先,我会保留一个辅助数组的布尔值,告诉我序列中的每个成员是否大于它之前的数字,表明这个数字是相对于前面的数字到位或顺序的。然后,我还会计算这些布尔值中有多少是真的。当存在的数字计数等于序列中的项目数时,将对序列进行排序。当对序列中的任何数字进行更改时,请使用以下算法进行检查:

float MySequence[LengthOfSequence];
bool IsNumInPlace[LengthOfSequence];
int CountOfNumsInPlace;

... something loads MySequence ...

// this starts that helper array of booleans
IsNumInPlace[0] = true;
CountOfNumsInPlace = 1;
for (i = 1; i < LengthOfSequence; i++) {
   IsNumInPlace[i] = (MySequence[i] > MySequence[i-1]);
   if (IsNumInPlace[i]) CountOfNumsInPlace++;
}


... something changes item at index "x" in the sequence ...
// whether this number, and possibly the one after it, are in place, needs
// to be rechecked
CheckThisItem(x);
if (x < LengthOfSequence - 1) CheckThisItem(x + 1);

... the array is sorted, at this point, if CountOfNumsInPlace is equal to the number of items in the array ...

关键在于这个小函数可以增加或减少“到位项目”的数量,具体取决于给定索引处的值是否大于或等于之前项目的值。

private void CheckThisItem(int ItemChanged) {
    bool IsNewNumInPlace= (ItemChanged == 0) ||
                          (MySequence[ItemChanged] >= MySequence[ItemChanged - 1]);
    if (IsNumInPlace[ItemChanged] && !IsNewNumInPlace) {
        CountOfNumsInPlace--;
    } else if (!IsNumInPlace[ItemChanged] && IsNewNumInPlace) {
        CountOfNumsInPlace++;
    }
    IsNumInPlace[ItemChanged] = IsNewNumInPlace;
}

这应该给你一个在O(n)中工作的算法。您不会重新比较数组中的每个项目与周围的项目,以查看数组是否按顺序排列,即使是那些未受影响的数组。您比较更改后的项目与之后的项目。

请注意,数组中的第一个项目被认为是与其之前的项目相关的“就地”。因为它之前没有任何项目(它是第一个),所以没有什么可以说它不合适,所以就排序而言它是“好的”。

如果您的操作对序列中的两个项目进行了更改,那么只需对最后一个部分执行两次,每次更改一次。