本问题已经有最佳答案,请猛点这里访问。
我正在努力解决以下提示背后的逻辑:未排序的整数数组包含从1到100的98个不同的数字。因此,在1到100的数字中,缺少两个不同的数字。 找到他们。
我理解找到一个缺失数字背后的概念,它是给我问题的第二个概念。 有什么建议?
是的,我已经看过这个条目了,但是我发现给出的答案要么太复杂,要么太详细,要么偏离主题。 我是一个java初学者 - 只是试图绕过这个。
编辑:这是我在跟随数字1-100启动数组然后对它们进行排序的地方:
for (int i = 0; i < arr.length; i++) {
int j = i + 1;
if (arr[j] - arr[i] > 1){
int missing = arr[i + 1];
System.out.println(missing);
}
}
我现在的问题是我无法得到循环来打印实际丢失的数字。 它打印的数字高于缺失的数字。 我尝试过几种不同的方法,它总是打印上面或下面的数字,而不是实际丢失的数字。
你可以发布你到目前为止所尝试的内容,以便我们可以尝试找到混淆的来源吗?
使用Sum(Euler)和Product(Factorial)您将需要BigInteger。 这将给你O(N)时间和O(1)存储。
在发布之前,你至少谷歌吗?
如果我没有,就不会发布。
@ pm77精确乘积,即n!,至少为O(n ^ 1.5)
对数组进行排序,然后进行循环,如果循环中的下一个元素不是前一个+ 1那么它就缺少一个。将先前的值保存为单独的变量,以便更多地区分数字。
你注意到未分类了吗?
你有没有注意到他的前两个词:"排序数组"?
@ PM77-1,是 - 因此"排序数组"。
未排序并不意味着 - 无法排序。
如果两个缺失的数字是连续的,这会有效吗?和/或如果其中一个缺失的数字是1?
它适用于所有情况,存储缺少的数字只需创建第二个数组
谁有人提出过这个问题?解决方案是O(n)时间和O(1)存储器。
@MaciejSikora我问过,因为如果你通过一个简单的检查在数组中做一个简单的循环,那么如果你有,例如,3和4缺失,你得到1和2,然后5. 5不是2 + 1,所以它会注意到3缺失。但是如果你只是在下一个元素(即5)处继续循环,它将永远不会找到另一个缺失的数字。如果缺少1,则必须在循环之前检查,否则将丢失。
@jonhopkins不是真的,例如缺少3,4,5然后3 - 前一个(是2)+1!= 6所以添加3并将前一个设置为3 - 下一个循环前一个(是3)+ 1!= 6所以加4然后下一个......
这就是我希望在答案中提到的伎俩。如果将previous存储为单独的变量并确保在找到缺失的数字时更新它并再次尝试相同的循环迭代,那么这将起作用。答案当前措辞的方式(在我看来)更像是"循环数组并检查最后一个元素是否是当前元素 - 1"
@jonhopkins谢谢,我编辑了答案并提到了这一点。
创建一个包含100个条目的"列表";每个值在启动时设置为false。
迭代你的数组,只需将每个条目作为布尔列表中的索引 - 并将值切换到true。
最后,布尔列表包含两个值false;他们的指数构成了两个缺失的数字。
使用array而不是List会更好,但你仍然有我的upvote。
这是为什么?我的意思是;为什么你喜欢阵列?因为初始分配有固定的大小?并感谢upvote;我真的很困惑为什么另一个问题得到了提升;在发布我的答案后2秒我得到了一个downvote。
我更喜欢一个数组,因为索引到它需要恒定的时间而不是与列表长度成比例的时间,并且没有缺点,因为数组/列表将始终是固定大小。
@ nhouser9是谁告诉过你的? ArrayList索引访问有O(1)[stackoverflow.com/questions/26638207/]
这是因为ArrayList是在幕后使用可以动态增长的数组实现的。这不是一个真正的清单。至于"谁告诉我",我在大学六年里学到了这一点。有关访问各种数据结构中元素的时间复杂性,请参阅此图片:image.slidesharecdn.com/
我还是不明白。索引是O(1),而不是O(n)。是的,添加元素在某些时候是昂贵的,但是如果你创建一个初始容量为100的列表,那么数组就没有区别了;除了使用收藏品给你的所有好处。
你缺少的是ArrayList实际上是array而不是List。
假设您的未排序的int数组被称为arr。现在创建一个包含100个元素的布尔数组,所有元素都初始化为false(默认值)。当您遍历arr时,将布尔数组中的相应元素标记为true。例如,如果arr中的第一个元素是20,则make visited[19]为true。执行此操作后,遍历布尔数组以查看哪两个索引为false,这将告诉您哪两个数字丢失。这是它应该是什么样子,
boolean visited = new boolean[100];
for(int i = 0; i < arr.length; i++){
visited[arr[i] - 1] = true;
}
for(int i = 0; i < visited.length; i++){
if(!visited[i]){
System.out.println(i + 1);
}
}
错误的答案。解决方案是O(N)时间和O(1)mem。查看标记的重复主题。
@xenteros答案没错。也许它不是最优的。但它给出了预期的输出。而这个问题本身并没有对时间和记忆Os施加任何限制。
这是一个受欢迎的问题。如果我问你关于排序你会给我log(n ^ 2)解决方案吗?
@xenteros正如GhostCast指出的那样,OP从未明确表示大O是这里的一个因素。但是,我确实看到了你的观点,我的回答并不是最有效的记忆。
@xen重要的是,它不需要排序,O(n)时间是最快的。唯一的缺点是O(n)空间复杂性,但它可以快速处理甚至大数量范围
@boh这是面试问题。如果你没有以最佳方式失败:)