查找已排序的循环整数数组的起始点的索引

时间:2015-11-16 13:46:26

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

有两个已排序的连续数字数组合并到一个数组中。 两个阵列都有不同的数字。

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);
  }
}

先谢谢。 : - )

3 个答案:

答案 0 :(得分:4)

二进制搜索也适合这里。对数的。

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;
}

答案 1 :(得分:0)

从你的描述中并没有完全清楚,但如果最小数字右边的所有数字都小于左边的所有数字,那么分而治之的算法就是这样的:

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

答案 2 :(得分:0)

你可以优化一下。你有这个代码的地方......

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

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

例如,如果mid处的号码小于low处的号码,那么您只需要拨打第一个号码,因为号码必须位于{{1}的左侧}。否则,你只需要拨打第二个。

这样可以加快速度。

如果这是面试的话,那么我建议你在工作时重构代码,这样就不会有条理。我认为你现在只是在玩弄一些工作。