arrays - 一次仅删除一个元素后,查找从父数组产生的已排序数组的数量

标签 arrays algorithm sorting data-structures

暴力方法是一次一个一个地删除每个数字,并检查结果数组是否已排序并维护此类排序数组的计数。这将花费 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])

最佳答案

相信我的时间复杂度为 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

关于arrays - 一次仅删除一个元素后,查找从父数组产生的已排序数组的数量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59332889/

相关文章:

arrays - 查找总和等于给定总和的所有唯一对

php - 基于日期时间mysql创建html select

java - java中如何只抓取二维矩阵的某一行?

algorithm - 如何从 map 转换MapResult!到整数数组?

algorithm - 在矩阵中找到最大可访问节点

algorithm - 给定最大匹配找到二分图的最小顶点覆盖

javascript - 根据预定义的顺序对字符串列表进行排序

JavaScript:根据条件创建二维对象数组

c - 如何在 C 中将 4 列文本文件读入两个字符数组?

c - 在 C 中定义数组