最少调用subArrayLeftShift方法对数组进行排序(面试问题)

时间:2018-09-01 10:21:23

标签: java arrays

假设您有一个方法subArrayLeftShift(a,i),当n为数组长度时,该方法向子数组a [i,...,n-1]左移。这意味着元素a [i + 1],...,a [n-1]向左移动一个位置,原始a [i]将成为最后一个。

更正式地说,这是函数的实现:

public static void subArrayLeftShift(int[] a, int i){
  if (a.length == 0) return;

  int last = a.length - 1;
  int insertToLast = a[i];
  for (; i < last; i++){
      a[i] = a[i + 1];
  }
  a[last] = insertToLast;
}

现在要提出的问题:实现一个函数,该函数接收未排序的数组,并返回对subArrayLeftShift进行数组排序的最小调用。

在采访中,我找不到解决方法。我成功找到了我为直觉编写的每个示例的最小调用次数,但是找不到将其概括的方法。

你知道如何解决吗?

2 个答案:

答案 0 :(得分:4)

我提出以下算法来解决该问题:

  • 在未排序的数组中查找最小数目(数组右边的数字较小)。将此数字设为 x
  • 计算数组中大于先前找到的数字 x 的数字。将此数字设为 y

由于每次调用该函数,未排序的数字都将在最后一个位置结束,因此最佳策略是按递增顺序为每个未排序的数字调用该函数。使用先前发现的内容,我们从 x 开始。我们继续使用下一个大于x的未排序数字,因为这样,它将最终出现在 x 的右侧,因此将对其进行排序。以相同的方式继续。多少?比我们的 x 大多少?好吧,这是 y 。因此,该函数的调用总数为 1 + y

答案 1 :(得分:1)

public static int minimumCalls(int[] a) {

    int minCalls = 0;

    for (int i = 0; i < a.length - 1; i++) {
        for (int j = i+1; j < a.length; j++) {
            if (a[i] > a[j]) {
                minCalls++;
                break;
            }
        }
    }

    return minCalls;
}

我的想法是,只要SubArray中存在小于当前i的任何值,就必须调用该方法一次。我觉得方法subArrayShiftLeft的名称旨在让您摆脱困境,并把注意力从容易想到的地方移开。

如果数组中的值小于当前值,只需调用该方法即可。

将其认为是将一个较大的值移动到数组的末尾要比尝试将较小的值向左移动要容易得多。