我正在尝试解决密码问题MissingInteger问题link:
写一个函数:
class Solution { public int solution(int[] A); }
给定N个整数的非空零索引数组A,返回A中不出现的最小正整数。 例如,给定:
A[0] = 1 A[1] = 3 A[2] = 6 A[3] = 4 A[4] = 1 A[5] = 2
该函数应返回5.
假设:
N是[1..100,000]范围内的整数; 数组A的每个元素都是[-2,147,483,648..2,147,483,647]范围内的整数。
复杂度:
预期的最坏情况时间复杂度为O(N); 预期的最坏情况空间复杂度是O(N),超出输入存储(不计入输入参数所需的存储)。 可以修改输入数组的元素。
我的解决方案是:
class Solution {
TreeMap<Integer,Object> all = new TreeMap<Integer,Object>();
public int solution(int[] A) {
for(int i=0; i<A.length; i++)
all.put(i+1,new Object());
for(int i=0; i<A.length; i++)
if(all.containsKey(A[i]))
all.remove(A[i]);
Iterator notOccur = all.keySet().iterator();
if(notOccur.hasNext())
return (int)notOccur.next();
return 1;
}
}
测试结果是:
任何人都可以解释我为什么会得到这两个错误的答案吗?特别是第一个,如果数组中只有一个元素,那么唯一正确的答案是不应该是1?
答案 0 :(得分:34)
这是我的答案,得到100/100。
import java.util.HashSet;
class Solution {
public int solution(int[] A) {
int num = 1;
HashSet<Integer> hset = new HashSet<Integer>();
for (int i = 0 ; i < A.length; i++) {
hset.add(A[i]);
}
while (hset.contains(num)) {
num++;
}
return num;
}
}
答案 1 :(得分:15)
返回A中未出现的最小正整数。
因此,在只有一个元素的数组中,如果该数字为1,则应返回2.如果不是,则应返回1.
我认为你可能会误解这些要求。您的代码正在基于给定数组的索引在地图中创建键,然后根据它在那里找到的值删除键。这个问题不应该与数组的索引有任何关系:它应该只返回给定数组中不是值的最低正整数。
因此,例如,如果您从1
迭代到Integer.MAX_VALUE
(包括),并返回不在给定数组中的第一个值,那将产生正确的答案。您需要确定要使用的数据结构,以确保您的解决方案在O(n)
进行扩展。
答案 2 :(得分:3)
我的回答是Denes的回答,但更简单。
int counter[] = new int[A.length];
// Count the items, only the positive numbers
for (int i = 0; i < A.length; i++)
if (A[i] > 0 && A[i] <= A.length)
counter[A[i] - 1]++;
// Return the first number that has count 0
for (int i = 0; i < counter.length; i++)
if (counter[i] == 0)
return i + 1;
// If no number has count 0, then that means all number in the sequence
// appears so the next number not appearing is in next number after the
// sequence.
return A.length + 1;
答案 3 :(得分:1)
返回A
中未出现的最小正整数
这里的关键是上面不包括零(因为它不是正整数)。因此该函数永远不会返回0.我相信这涵盖了上述两种失败案例。
编辑:由于问题已经改变,因为这个问题已经改变了
答案 4 :(得分:0)
非常错误。 只是最后一行
return 1;
应该阅读
return A.length + 1;
因为此时你已经找到了&amp;将ALL KEYS从1移到A.length,因为您有与每个键匹配的数组条目。测试要求在这种情况下,您必须返回高于数组A中找到的最大值的下一个整数。 通过返回迭代下找到的第一个未删除的密钥,可以覆盖所有其他可能性(例如,否定条目,缺少1,缺少1和A.length之间的数字)。这里的迭代是由#34;自然排序&#34;完成的,即1 .. max,默认情况下是TreeMap。因此,第一个未删除的密钥将是最小的缺失整数。
此更改应使2次不正确的测试再次正常。所以100%的正确性。
效率当然是另一回事。 在此处使用TreeMap数据结构会在评估测试结果时带来时间损失。更简单的数据结构(基本上使用您的算法)会更快。
这种更原始的算法避免了排序和复制所有条目&gt; 1到一个长度为100001的新数组上,使索引x保持值x。它实际上比Serdar的代码运行得更快,具有中型和大型输入数组。
public int solution(int[] A)
{
int i = 0,
count = 0,
N = A.length;
int[] B = new int[100001]; // Initially all entries are zero
for (i = 0; i < N; i++) // Copy all entries > 0 into array B ...
if (A[i] > 0 && A[i] < 100001)
{
B[A[i]] = A[i]; // ... putting value x at index x in B ...
count++; // ... and keep a count of positives
}
for (i = 1; i < count + 1; i++) // Find first empty element in B
if (B[i] == 0)
return i; // Index of empty element = missing int
// No unfilled B elements above index 0 ?
return count + 1; // => return int above highest filled element
}