【问题标题】:Finding a single integer in an array在数组中查找单个整数
【发布时间】:2015-05-19 17:34:39
【问题描述】:

我正在尝试解决算法问题。我需要在数组中找到一个整数

例如 {1,1,5,5,5,3,2,2}

输出应该是 3,因为这是那里唯一的单个整数。

到目前为止,我创建了一个算法,首先我对数组进行排序,然后检查 i-1 和 i+1 元素是否相等,如果不相等,则表示我只有一个。

问题是;对于短输入,它工作正常,但对于长输入,我会收到超时(计算时间太长,所以我的答案没有得到验证)。

你能给我一些改进算法的建议吗

static int lonelyinteger(int[] a) {

    Arrays.sort(a);

    if (a.length == 1)
        return a[0];

    for (int i = 0; i < a.length; ++i) {

        if (i == 0) {
            if (a[i + 1] != a[i])
                return a[i];
        } else if (i == a.length - 1) {
            if (a[i] != a[i - 1])
                return a[i];
        } else {
            if (a[i - 1] != a[i] && a[i + 1] != a[i])
                return a[i];
        }  
    }
    return -1;
}

【问题讨论】:

  • 举一个导致这种情况发生的输入示例。
  • 你得到了什么确切的例外? (带堆栈)
  • 您不需要对数组进行排序。遍历它一次,并构建一个你看到的每个数字的地图,以及你看到它的次数。然后用 counter == 1 打印数字。
  • 你说的超时是什么意思?
  • map 的想法是可行的,但请记住,与就地排序相比,它所需的内存大约是三倍(取决于有多少单个条目和多个条目)。对于较小的 N 无关紧要,但对于相对于可用内存而言非常大的 N 会。

标签: java arrays algorithm


【解决方案1】:

对于这个问题,O(N^2) 是否不够“快”?

在这里,我有一个包含 10,000,000 个随机对值的元素的列表。在一个随机的地方,我把“孤独的整数” 5,并且 O(N^2) 快速解决它而不需要排序。该算法在它找到的第一个“孤立整数”处停止。

public static void main(String[] args) {
    Random r = new Random();

    List<Integer> ints = new ArrayList<>();
    for (int i = 0; i < 10000000; i += 2) {
        int randomNumber = r.nextInt(100) + 10;
        ints.add(randomNumber);
        ints.add(randomNumber);
    }
    ints.add(5); // Lonely Integer

    int tempIndex = r.nextInt(ints.size());
    int tempValue = ints.get(tempIndex);
    // Swap duplicate integer with lonely integer
    ints.set(tempIndex, ints.get(ints.size() - 1)); 
    ints.set(ints.size() - 1, tempValue);

    for (int i = 0; i < ints.size(); i++) {
        boolean singleInteger = true;
        for (int j = 0; j < ints.size(); j++) {
            if (j == i) {
                continue;
            }
            if (ints.get(j) == ints.get(i)) {
                singleInteger = false;
                break;
            }
        }

        if (singleInteger) {
            System.out.println("Single instance: " + ints.get(i));
            break;
        }
    }
}

结果:

单个实例:5(大约 10 - 20 秒);

更新

你的方法大约 3 秒。

地图解决方案...

public static void main(String[] args) {
    Random r = new Random();

    List<Integer> ints = new ArrayList<>();
    for (int i = 0; i < 10000000; i += 2) {
        int randomNumber = r.nextInt(100) + 10;
        ints.add(randomNumber);
        ints.add(randomNumber);
    }
    ints.add(5); // Lonely Integer
    int tempIndex = r.nextInt(ints.size());
    int tempValue = ints.get(tempIndex);
    // Swap duplicate integer with lonely integer
    ints.set(tempIndex, ints.get(ints.size() - 1));
    ints.set(ints.size() - 1, tempValue);

    Map<Integer, Integer> counts = new HashMap<>();
    for (int i : ints) {
        if (counts.containsKey(i)) {
            counts.put(i, counts.get(i) + 1);
        } else {
            counts.put(i, 1);
        }
    }

    for (Integer key : counts.keySet()) {
        if (counts.get(key) == 1) {
            System.out.println("Single Instance: " + key);
        }
    }
}

结果:

单实例:5(大约 1 - 3 秒)

【讨论】:

  • @sodium24 是的...在将随机数字对与所有相同数字放在一起后,我撤回了查找多个“孤独整数”的更新。之后,我想确保在随机对中找到第一个“孤独的整数”,并且仍然有效。
  • 对不起我正在研究算法的菜鸟问题,我并不真正了解如何计算时间复杂度,但是,我认为我当前的解决方案具有 O(n*logn) 复杂度,不是 O (N^2) 比那更糟。
  • @waff 是的... O(N * logN) 比 O(N^2) 快,但你的算法真的是 O(N * logN),因为你正在调用 Arrays.sort (a)?
  • Arrays.sort 是一种快速排序方法,平均为 O(n log(n))。至少谷歌是这么说的。但我又不是专家。 bigocheatsheet.comdocs.oracle.com/javase/7/docs/api/java/util/…
  • @waff 是的,我也读过,但是你在 O(N * logN) 排序之后进行 O(n) 搜索。两者结合起来仍然比 O(n^2) 快吗?我还在学习 O 表示法。
【解决方案2】:

你确定你的问题是正确的吗?孤独整数算法问题(通常发布在算法解决挑战中)背后的想法是,所有数字都成对出现,除了一个。从您使用的示例来看,情况并非如此。

如果所有数字都成对显示,除了一个,找到解决方案的最快方法是对所有元素应用 XOR。由于在两个相同元素之间应用 XOR 会取消它们,因此您将获得您正在寻找的孤独整数。此解决方案的时间复杂度为 O(n)。

否则,如果在给定数组中找到一个数超过两次,或者您正在使用您提供的解决方案,则时间复杂度为 O(n*logn)。

【讨论】:

  • 这个问题是对的。我只是想问是否有任何方法可以改进解决方案,以便它可以比现在更快地工作。
  • 抱歉误导了,在这种情况下。
【解决方案3】:

首先检查不是Arrays.sort(a); 对于非常大的输入来说花费的时间太长。

如果不是这样,你可以改进你的方法如下

 static int lonelyinteger(int[] a) {
    if (a[0] != a[1]) return a[0];

    int i = 1;
    while ((i < a.length - 1) && (a[i] == a[i-1] || a[i] == a[i+1])) {
        i++;
    }

    if ((i < a.length -1) || (a[i] != a[i-1]))  return a[i];
    return -1;
}

【讨论】:

    【解决方案4】:

    排序。那么……

    while (true) {
        if (a[0] != a[1]) {
            return a[i].
      } else {
          remove all a[0]s from a.
      }
    }
    

    这是 O(nlogn)。

    找到所有唯一整数的 O(n) 解决方案(一个无排序)是有一个散列并沿着数组运行。如果数字未出现在哈希中,请将数字添加到其中。如果它确实出现在散列中,请从散列中删除该数字。最后,您将在一个哈希中拥有所有唯一整数。繁荣。

    【讨论】:

      猜你喜欢
      • 2017-06-18
      • 2015-05-13
      • 1970-01-01
      • 1970-01-01
      • 2015-12-08
      • 1970-01-01
      • 2015-08-23
      • 1970-01-01
      相关资源
      最近更新 更多