【问题标题】:Find number of sorted arrays resulting from parent array after removing exactly one element at a time一次仅删除一个元素后查找从父数组产生的排序数组的数量
【发布时间】:2020-04-07 12:22:22
【问题描述】:

蛮力方法是一次一个地删除每个数字,并检查结果数组是否已排序并维护此类排序数组的计数。这需要 O(n^2) 时间。

还有其他方法可以在小于 O(n^2) 的时间内找到计数吗?

注意:每次只删除一个元素后,只需要查找此类排序数组的计数。

例如:

输入:[1 2 3 4 5 4]

输出:2([1 2 3 4 4],[1 2 3 4 5])

输入:[1 2 3 4 2]

输出:1 ([1 2 3 4])

【问题讨论】:

  • 数组中是否可以有两个递减对,并且答案大于 0? (递减对是数组中的两个相邻元素,其中较大的在前。)
  • 您只需要查找违规元素,例如第一个示例中的最后一个元素。然后还要考虑之前索引处的元素。如果没有违规者,即所有内容都已排序,您可以选择任何一个元素。如果有多个,您可以开始分支以备将来使用。

标签: arrays algorithm sorting data-structures


【解决方案1】:

相信我将这个时间缩短到 O(n) 时间 - 该算法只执行一次遍历列表,检查每个元素一次。


对于每个元素:

  • 如果下一个元素大于或等于当前元素,则继续。
  • 如果下一个元素小于当前元素...
    • (设置失败位。如果该位已设置,则停止检查。)
    • 如果这个元素前面两个索引的元素相对于这个元素排序,这意味着我们可以省略下一个元素并且仍然被排序。添加匹配项。
    • 如果该元素后面的元素一索引相对于该元素之前的元素一索引进行排序,这意味着我们可以省略当前元素并且仍然被排序。添加匹配项。

一旦完成运行,代码将检查失败位。

  • 如果未设置失败位,则所有内容都已排序,并且可能列表的数量等于列表中元素的数量。
  • 如果设置了失败位,则存在一个未排序的元素。记录匹配次数。
  • 如果设置了失败位并且循环提前退出,则至少有两个未排序的元素 - 不可能匹配。

EXAMPLE - steps are in reverse order

STEP  1 3 4 6 5 7 8
7                 ^ 8<=(end), pass
6               ^ 7<=8, pass
5             ^ 5<=7, pass
4b          ^   ^ 6<=7, we can safely omit next element (5) - add match
4a        ^   ^ 4<=5, we can safely omit current element (6) - add match
4           ^ 6!<=5, set failure bit
3         ^ 4<=6, pass
2       ^ 3<=4, pass
1     ^ 1<=3, pass

下面是cpp中的一个实现。请注意,向量被填充以避免对第一个或最后一个元素进行额外的边界检查逻辑。

#include <iostream>
#include <vector>
#include <climits>

int main(void) {

  std::vector<int> invals;
  int temp = 0;

  //pad the vector to get around out-of-bounds checking
  invals.push_back(INT_MIN);
  invals.push_back(INT_MIN);

  //get user input
  std::cout << "enter vals, ctrl_d to calculate" << std::endl;

  while(std::cin >> temp) { invals.push_back(temp); }

  //padding
  invals.push_back(INT_MAX);
  invals.push_back(INT_MAX);

  int matches = 0;
  int fail = 0;
  for(int i = 2; i < invals.size() - 2; i++) {
    //sorted - continue
    if(invals[i] <= invals[i+1]) { continue; }

    //something was unsorted
    else {

      //there was already another unsorted element - this list cannot
      //be sorted by removing just 1 element. break and fail
      if(fail == 1) { fail = 2; break; }

      else {
        //set fail bit
        fail = 1;

        //check if the next element can be removed
        if(invals[i] <= invals[i+2]) { matches++; }

        //check if this element can be removed
        if(invals[i-1] <= invals[i+1]) { matches++; }
      }
    }
  }

  std::cout << "\n\nmatches: ";
  if(fail == 0) { std::cout << invals.size() - 4 << std::endl; }
  else if(fail == 1) { std::cout << matches << std::endl; }
  else if(fail == 2) { std::cout << 0 << std::endl; }

  return(0);

}

Demo

【讨论】:

  • 故障位逻辑有效,但如果我们跟踪递减的对,并且如果此类对的数量大于 1,则无法解决;如果为0,则所有内容都已排序,解决方案是父数组大小;如果是 1,则可以产生 1 或 2 个排序数组。这个逻辑看起来不错?
  • @MushiMaster 这听起来对我来说是正确的,我认为逻辑很好。如果是一对降序,只需要确定匹配的数量。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-20
  • 2012-01-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多