自从我讨论任何编码或算法面试问题以来已经有很长时间了,因此我想重新考虑一种最流行的基于数组的编码问题,即在给定数组中查找缺失的数字。 在进行编程工作面试之前,您可能已经听说过或看到过此问题,但是面试官通常会使用许多不同的版本来提高难度,以使候选人感到困惑并进一步测试其适应频繁变化的能力。 过去,我已经演示了如何使用BitSet在Java中的未排序整数数组上以及在排序数组中查找缺失的数字 (请参阅此处 ),但是,只有一个缺失的数字并且没有任何重复。
这使问题有些容易,但是如果面试官告诉您数组包含重复项并且缺少多个数字,您该怎么办? 好吧,这就是我们将在本文中讨论的内容,但是在此之前,让我们正确地获取问题说明。
1.问题陈述:
您给定了一个大小为N的整数数组。该数组包含从1到N-1的数字,但是在包含重复项的数组中缺少几个数字。 编写一个Java程序以打印序列中缺少的数字。
例如,如果给定数组为
{1,1,2,3,5,5,7,9,9,9}那么它的长度
10,其中包含1到9之间的数字。在这种情况下,缺少的数字是4、6和8。
2.解决方案:
当你看到的问题是找到阵列失踪人数 ,你可能会认为我们前面的解决方案计算所有数字的总和 ,并从预期的总和扣除它来寻找失踪的数字,但不幸的是不会在这种情况下工作,因为更多缺少一个数字 ,并且其中包含重复项。
在这种情况下,我们需要使用其他方法,例如您在学校中看到的点名通话。
老师有一个列出所有学生姓名的登记册,他在列表中浏览并用红色标记缺席。 我们可以使用相同的方法来查找列表中所有缺少的数字。
我们可以将数组用作寄存器,并将索引用作数字名称。 我们遍历给定的数组,并通过存储它们各自的索引之一来标记所有存在的数字。 例如,如果给定数组中的第一个数字为5(由于未对数组进行排序),则我们将1存储在索引5中,例如register[5] = 1
给定所有数字后,就可以遍历寄存器数组并打印所有值为零的索引。 这些人缺席或缺席。
该解决方案对于重复项也是安全的,因为如果一个数字出现一次或两次,我们只需将1存储在相应的索引中即可。
3.代码:
现在,我们知道如何解决带有重复项的未排序整数数组中的数字遗漏的问题,是时候将该解决方案变成代码并运行Java程序了。
/** Java Program to find missing numbers in an integer* array with duplicates. Array may contains more* than one duplicates.* * input: {1, 1, 2, 3, 5, 5, 7, 9, 9, 9};* output: 4, 6, 8*/
public class Hello {public static void main(String[] args) {// given inputint[] input = { 1, 1, 2, 3, 5, 5, 7, 9, 9, 9 };// let's create another array with same length// by default all index will contain zero// default value for int variableint[] register = new int[input.length];// now let's iterate over given array to// mark all present numbers in our register// arrayfor (int i : input) {register[i] = 1;}// now, let's print all the absenteesSystem.out.println("missing numbers in given array");for (int i = 1; i < register.length; i++) {if (register[i] == 0) {System.out.println(i);}}}}
Output
missing numbers in given array
4
6
8
这是解决此问题的最简单的Java程序。 您可以看到我们已经对输入数组进行了硬编码,但是您也可以修改程序以通过使用Scanner类从用户获取输入,如本示例所示。
该代码与解决方案完全相同,我们通过复制原始数组的长度来创建另一个数组,并使用它标记存在的数字。
由于数组索引也是整数,并且它们在输入值的范围内,因此我们可以利用它们将其用作数据和元数据。 如果数组中包含的数字不在1到N-1之间,那么我们就不能使用数组。
以下是幻灯片中算法和代码的摘要,以使您更好地理解:
4.分析
现在,是时候分析我们的解决方案,以便使用Big O表示法查找CPU和内存的复杂性。 如果看一下代码,您会发现我们正在创建另一个具有相同大小的数组,这意味着它的内存或空间复杂度为O(n) 。
这意味着如果数组太大,即包含整数范围内的所有数字,那么我们将有更多的内存可能不可用,并且我们的程序可能会在Java中抛出OutOfMemoryError 。 这甚至更有可能,因为数组需要连续的内存块。
因此,如果我们可以删除实际上不容纳任何内容的附加数组,并找到一种方法来存储丢失的数字,而该数字远远小于我们可以改进此解决方案的所有数字,那么您可以考虑一下。
对于时间复杂度 ,您可以看到我们遍历整个数组以标记所有存在的数字,然后再次遍历具有相同长度的另一个数组以查找缺席者。 这意味着该解决方案的时间复杂度为O(n)+ O(n)或O(2N),但仍为Big O表示法仍为O(n) 。
如果我们找到在给定数组中进行迭代时打印缺席者的方法,则可以进一步改进此解决方案。 再说一遍,你们要想一想。
这就是在给定整数array中查找缺失数字的经典问题 。 在这一部分中,我们找到了一种解决方案,该解决方案可在未排序的重复数组中查找多个缺失的数字。 我们解决方案的时间和空间复杂度为O(n)。
翻译自: https://www.javacodegeeks.com/2018/04/how-to-find-k-missing-numbers-in-integer-array-with-duplicates-in-java.html