【问题标题】:Array with Consecutive numbers - Algorithm具有连续数字的数组 - 算法
【发布时间】:2016-04-20 11:23:51
【问题描述】:

我正在尝试回答以下问题:给定一个包含一些有序数字和一些非序列数字的排序数组,编写一个算法,为每组连续数字获取一对 {start, end}。连续数的差值只有 1。

到目前为止,我只能想到蛮力方法:

public static void main(String[] args) {
    int[] array = { 4, 5, 6, 7, 8, 9, 12, 15, 16, 17, 18, 20, 22, 23, 24, 27 };
    Map<Integer, Integer> list = new HashMap<Integer, Integer>();

    list = findIndex(array);
}

// Bruteforce
private static Map<Integer, Integer> findIndex(int[] array) {
    Map<Integer, Integer> list = new HashMap<Integer, Integer>();

    int x = -1, y = -1;

    int end = array.length;
    for (int i = 0; i < end; i++) {
        x = i;
        while (i < end - 1) {

            if (array[i] + 1 == array[i + 1]) {
                i++;
                y = i;
            } else {
                if (x != y && x >= 0) {
                    list.put(x, y);
                    System.out.println("i = " + x + " to j = " + y);
                    i = i + 1;
                    break;
                }
            }
        }

    }
    return list;
}

输出:

i = 0 to j = 5
i = 7 to j = 10
i = 12 to j = 14

效果很好,但是如何提高时间复杂度?

【问题讨论】:

  • 代码的问题不在于算法复杂性,而在于清晰度。这段代码实际上只在数组中迭代一次,尽管嵌套循环掩盖了这一点。 O(n) 是你能做的最好的。
  • @AndrewPalmer 我们不能在这里使用二分搜索吗?
  • 我不得不说这是一个非常有趣的想法。这绝对不是二分搜索的标准应用,但根据数组的保证,您可以确定有 8 个间隙并开始缩小间隙的位置。
  • @Sarah 不,因为如果不查看序列的所有元素,就无法知道序列中是否有任何讨厌的乱序数。假设在一个完美序列的未知位置存在单个异常值(例如:1 2 3 0 5),二分查找无法帮助您找到它。

标签: java arrays algorithm data-structures


【解决方案1】:

你不需要为此嵌套循环:

int end = array.length;
if (end > 0) {
    int start = 0;
    for (int i = 1; i < end; i++) {
        if (array[i] != array[i - 1] + 1) {
            if (i - start > 1) {
                list.put(start, i - 1);
                System.out.println("i = " + start + " to j = " + (i - 1));
            }
            start = i;
        } 
    }
    if (end - start > 1) {
        list.put(start, end - 1);
        System.out.println("i = " + start + " to j = " + (end - 1));
    }
}

【讨论】:

    【解决方案2】:

    只要对初始数组进行排序,您就可以像这样对该算法进行 O(N) 实现:

    private static Map<Integer, Integer> getConsecutive(final int[] array) {
        final Map<Integer, Integer> list = new TreeMap<Integer, Integer>();
        int startIndex = 0;
        int endIndex = 0;
        for (int i = 1; i < array.length; i++) {
            if (array[i - 1] + 1 == array[i])
                endIndex = i;
            else {
                if (endIndex > startIndex)
                    list.put(startIndex, endIndex);
                startIndex = endIndex = i;
            }
        }
        if (endIndex > startIndex)
            list.put(startIndex, endIndex);
        return list;
    }
    

    【讨论】:

    • 这不会产生与问题中的代码相同的结果。一方面,它不会忽略孤立的数字,例如示例输入中的 12、20 和 27。
    • @JohnSensebe 它会忽略它们
    • 我们可以用二分搜索来做到这一点吗?
    • @Sarah 不,你需要检查每个元素至少一次,因为可能有重复
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-25
    • 2011-01-18
    • 1970-01-01
    • 1970-01-01
    • 2018-07-28
    • 2020-02-17
    • 2021-07-30
    相关资源
    最近更新 更多