【问题标题】:Find index of starting point of a sorted cyclic integer array查找已排序循环整数数组的起点索引
【发布时间】:2016-02-17 15:23:13
【问题描述】:

有两个排序的连续数数组合并为一个数组。 两个数组都有不同的数字。

ex : 
{1, 2, 3, 4, 5, 6, 7, 8, 9}   and
{10, 11, 12, 13, 14}

int[] resultArr = {10, 11, 12, 13, 14, 1, 2, 3, 4, 5, 6, 7, 8, 9};
                                      ^

寻找起点索引的算法。如果我们将其视为循环数组,它将在从起点迭代时按排序顺序进行。

在上面的例子中,起始索引将是 "4"

我写了下面的示例程序来解决这个问题,但对时间复杂度不满意。

谁能告诉我以下代码的时间复杂度,并为这个问题提供更好的解决方案。

public class FindStartingPoint {

  public static Integer no = null;

  private static void findStartingPoint(int[] arr, int low, int mid, int high) {
    if (no != null)
      return;
    else if (high - low <= 1)
      return;
    else if (arr[mid] > arr[mid + 1]) {
      no = mid + 1;
      return;
    }
    findStartingPoint(arr, low, (low + mid) / 2, mid);
    findStartingPoint(arr, mid, (mid + high) / 2, high);
  }

  public static void main(String[] args) {
    int[] arr = {12, 13, 14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
    findStartingPoint(arr, 0, arr.length / 2, arr.length - 1);
    System.out.println(no);
  }
}

提前致谢。 :-)

【问题讨论】:

  • 等一下,你是不是要在数组中找到最小的数字?
  • @JordanSeanor ,不,我正在尝试找出最低 no 数组的索引(这将是起点)
  • 如果两个数组分别是{1,2,3}{4,5,6},则没有解决办法,所以仅仅排序并有不同的元素是不够的。
  • @biziclop,结果数组未排序。考虑一下,具有较大 no 的数组首先出现。在您的示例中,它将是 {4,5,6} 和 {1,2,3}。结果数组将是 {4,5,6,1,2,3},答案是“3”,它是数字“1”的索引
  • @ManosNikolaidis 不一定。如果最小的数字右边的所有数字都小于左边的所有数字,则可以分而治之。

标签: java arrays algorithm time-complexity divide-and-conquer


【解决方案1】:

二分搜索也适合这里。对数。

public int findStart(int[] numbers) {
    int low = 0;
    int high = numbers.length; // Exclusive
    while (low < high) {
        int middle = (low + high) / 2;
        boolean fitsLow = numbers[low] <= numbers[middle];
        if (fitsLow) {
            low = middle + 1;
        } else {
            high = middle;
        }
    }
    return low;
}

【讨论】:

  • @biziclop - 使用 Dijkstra 的 [low, high) 约定
  • 是的,评论后立即意识到。 :)
【解决方案2】:

从你的描述中不是很清楚,但是如果最小数字右侧的所有数字都小于左侧的所有数字,那么分治算法的工作原理如下:

  1. 从第一个元素的左边界和最后一个元素的右边界开始。
  2. 取左右边界中间的元素。
  3. 如果中间元素大于左边界,请将左边界移动到中间元素。
  4. 如果中间元素小于左边界,请将右边界移动到中间元素。
  5. 从 2 开始重复,直到您的范围内只有 1 个元素。

【讨论】:

    【解决方案3】:

    你可以优化一下。你在哪里有这个代码......

    findStartingPoint(arr, low, (low + mid) / 2, mid);
    findStartingPoint(arr, mid, (mid + high) / 2, high);
    

    你实际上只需要调用其中一个而不是两个。

    例如,如果mid 的号码小于low 的号码,那么您只需拨打第一个号码,因为号码必须在mid 的左侧。否则,您只需要调用第二个即可。

    这会加快速度。

    如果这是为了面试,那么我建议您在代码正常运行时重构代码,以减少有状态的代码。不过,我假设您只是在玩弄目前正在运行的东西。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-01-07
      • 1970-01-01
      • 1970-01-01
      • 2022-01-01
      • 2012-12-24
      • 2021-02-03
      • 2020-06-28
      • 1970-01-01
      相关资源
      最近更新 更多