我对Codility MissingInteger的Java解决方案有什么问题?

时间:2014-10-23 15:48:46

标签: java

我正在尝试解决密码问题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;

    }
}

测试结果是:

enter image description here

任何人都可以解释我为什么会得到这两个错误的答案吗?特别是第一个,如果数组中只有一个元素,那么唯一正确的答案是不应该是1?

5 个答案:

答案 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
}