Missing integer variation - O(n) solution needed
该问题来自Codility编程培训,听起来像是:
我们有一个数组(A []??),其中包含n个元素(范围从1到100,000),这些是我们的参数。数组的元素是从?2,147,483,648到2,147,483,647的整数,我们需要找到不在数组中的最小正整数。当然,这可以在O(n * log n)中轻松完成,方法是将它们全部排序并通过排序后的数组,查找丢失的正数(在我的解决方案中,此最后一个操作的时间复杂度为O(n))。但是根据Codility,整个问题都可以在O(n)中完成,而我看不到任何解决方法。有人可以给我一些提示让我摆脱困境吗?
PS这是指向我不允许复制的问题的详细说明的链接-https://codility.com/c/intro/demo35UEXH-EAT
根据信鸽原理,数字1、2,...,n 1中的至少一个不在数组中。
让我们创建一个大小为n 1的布尔数组
现在,我们处理输入数组。如果找到从1到n 1的数字,则会在
完成输入处理后,我们可以在O(n)中轻松找到布尔数组
使用Java的简单解决方案100%。
请注意,它是O(nlogn)解决方案,但100%产生了codility。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public static int solution(final int[] A) { Arrays.sort(A); int min = 1; // Starting from 1 (min), compare all elements, if it does not match // that would the missing number. for (int i : A) { if (i == min) { min++; } } return min; } |
今天写了这个,得到了100/100。不是最优雅的解决方案,但易于理解-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | public int solution(int[] A) { int max = A.length; int threshold = 1; boolean[] bitmap = new boolean[max + 1]; //populate bitmap and also find highest positive int in input list. for (int i = 0; i < A.length; i++) { if (A[i] > 0 && A[i] <= max) { bitmap[A[i]] = true; } if (A[i] > threshold) { threshold = A[i]; } } //find the first positive number in bitmap that is false. for (int i = 1; i < bitmap.length; i++) { if (!bitmap[i]) { return i; } } //this is to handle the case when input array is not missing any element. return (threshold+1); } |
构建所有值的哈希表。对于数字1到n 1,检查它们是否在哈希表中。至少其中一个不是。打印出最低的数字。
这是O(n)个预期时间(您很有可能获得)。请参阅@Gassa的答案,以了解如何避免使用哈希表,而使用大小为O(n)的查找表。
简单的Java语言。在正确性和性能方面得分100/100。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public int solution(int[] A) { int smallestMissingInteger = 1; if (A.length == 0) { return smallestMissingInteger; } Set<Integer> set = new HashSet<Integer>(); for (int i = 0; i < A.length; i++) { if (A[i] > 0) { set.add(A[i]); } } while (set.contains(smallestMissingInteger)) { smallestMissingInteger++; } return smallestMissingInteger; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public int solutionMissingInteger(int[] A) { int solution = 1; HashSet<Integer> hashSet = new HashSet<>(); for(int i=0; i<A.length; ++i){ if(A[i]<1) continue; if(hashSet.add(A[i])){ //this int was not handled before while(hashSet.contains(solution)){ solution++; } } } return solution; } |
JavaScript 100%
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | function solution(A) { let sortedOb = {}; let biggest = 0; A.forEach(el => { if (el > 0) { sortedOb[el] = 0; biggest = el > biggest ? el : biggest; } }); let arr = Object.keys(sortedOb).map(el => +el); if (arr.length == 0) return 1; for(let i = 1; i <= biggest; i++) { if (sortedOb[i] === undefined) return i; } return biggest + 1; } |
C#得分100%,
说明:使用查找表存储从输入数组中已经看到的值,我们只关心大于0且小于或等于输入数组上的长度的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public static int solution(int[] A) { var lookUpArray = new bool[A.Length]; for (int i = 0; i < A.Length; i++) if (A[i] > 0 && A[i] <= A.Length) lookUpArray[A[i] - 1] = true; for (int i = 0; i < lookUpArray.Length; i++) if (!lookUpArray[i]) return i + 1; return A.Length + 1; } |
100%Javascript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | function solution(A) { // write your code in JavaScript (Node.js 4.0.0) var max = 0; var array = []; for (var i = 0; i < A.length; i++) { if (A[i] > 0) { if (A[i] > max) { max = A[i]; } array[A[i]] = 0; } } var min = max; if (max < 1) { return 1; } for (var j = 1; j < max; j++) { if (typeof array[j] === 'undefined') { return j } } if (min === max) { return max + 1; } } |
我的解决方案。 100%。在Java中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Solution {
public int solution(int[] A) {
Arrays.sort(A);
ArrayList<Integer> positive = new ArrayList<>();
for (int i = 0; i < A.length; i++) {
if(A[i] > 0)
positive.add(A[i]);
}
if(positive.isEmpty()) return 1;
if(positive.get(0) > 1) return 1;
for(int i = 0; i < positive.size() - 1; i++) {
if(positive.get(i + 1) - positive.get(i) > 1)
return positive.get(i) + 1;
}
return positive.get(positive.size() - 1) + 1;
}
public static void main(String[] args) {
Solution solution = new Solution();
int[] A = {-5,1,2,3,4,6,7,8,9,5};
System.out.println(solution.solution(A));
}
}
这是我的解决方案,是Swift 4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public func solution(_ A: inout [Int]) -> Int { var minNum = 1 var hashSet = Set<Int>() for int in A { if int > 0 { hashSet.insert(int) } } while hashSet.contains(minNum) { minNum += 1 } return minNum } var array = [1,3,6] solution(&array) |
//答案:2
javascript 100%100%
首先对数组进行排序,您只需要扫描正元素即可找到索引1(如果数组中没有1,则答案为1)。然后在1之后搜索元素,直到找到缺失的数字。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | function solution(A) { // write your code in JavaScript (Node.js 6.4.0) var missing = 1; // sort the array. A.sort(function(a, b) { return a-b }); // try to find the 1 in sorted array if there is no 1 so answer is 1 if ( A.indexOf(1) == -1) { return 1; } // just search positive numbers to find missing number for ( var i = A.indexOf(1); i < A.length; i++) { if ( A[i] != missing) { missing++; if ( A[i] != missing ) { return missing; } } } // if cant find any missing number return next integer number return missing + 1; } |
100%:Python排序例程不被视为作弊...
1 2 3 4 5 6 7 8 9 10 11 | def solution(A): """ Sort the array then loop till the value is higher than expected """ missing = 1 for elem in sorted(A): if elem == missing: missing += 1 if elem > missing: break return missing |
我相信解决方案比使用n(100,000)个元素的布尔数组"标记"相应的值更复杂。大小为n的布尔数组不会直接映射到可能的值范围(?2,147,483,648到2,147,483,647)。
我写的这个Java示例尝试通过基于距最大值的偏移量映射值来映射100K行。它还执行模量以将所得数组减小到与样本元素长度相同的大小。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | /** * * This algorithm calculates the values from the min value and mods this offset with the size of the 100K sample size. * This routine performs 3 scans. * 1. Find the min/max * 2. Record the offsets for the positive integers * 3. Scan the offsets to find missing value. * * @author Paul Goddard * */ public class SmallestPositiveIntMissing { static int ARRAY_SIZE = 100000; public static int solve(int[] array) { int answer = -1; Maxmin maxmin = getMaxmin(array); int range = maxmin.max - maxmin.min; System.out.println("min: " + maxmin.min); System.out.println("max: " + maxmin.max); System.out.println("range:" + range); Integer[] values = new Integer[ARRAY_SIZE]; if (range == ARRAY_SIZE) { System.out.println("No gaps"); return maxmin.max + 1; } for (int val: array) { if (val > 0) { int offset = val - maxmin.min; int index = offset % ARRAY_SIZE; values[index] = val; } } for (int i = 0; i < ARRAY_SIZE; i++) { if (values[i] == null) { int missing = maxmin.min + i; System.out.println("Missing:" + missing); answer = missing; break; } } return answer; } public static Maxmin getMaxmin(int[] array) { int max = Integer.MIN_VALUE; int min = Integer.MAX_VALUE; for (int val:array) { if (val >=0) { if (val > max) max = val; if (val < min) min = val; } } return new Maxmin(max,min); } public static void main(String[] args) { int[] A = arrayBuilder(); System.out.println("Min not in array:" + solve(A)); } public static int[] arrayBuilder() { int[] array = new int[ARRAY_SIZE]; Random random = new Random(); System.out.println("array:"); for (int i=0;i < ARRAY_SIZE; i++) { array[i] = random.nextInt(); System.out.print(array[i] +","); } System.out.println(" array done."); return array; } } class Maxmin { int max; int min; Maxmin(int max, int min) { this.max = max; this.min = min; } } |
对我有用。它不是O(n),但是简单得多:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import java.util.stream.*; class Solution { public int solution(int[] A) { A = IntStream.of(A) .filter(x->x>0) .distinct() .sorted() .toArray(); int min = 1; for(int val : A) { if(val==min) min++; else return min; } return min; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | int[] copy = new int[A.length]; for (int i : A) { if (i > 0 && i <= A.length) { copy[i - 1] = 1; } } for (int i = 0; i < copy.length; i++) { if (copy[i] == 0) { return i + 1; } } return A.length + 1; |
迅捷3-100%
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public func solution(_ A : inout [Int]) -> Int { // write your code in Swift 3.0 (Linux) var solution = 1 var hashSet = Set<Int>() for int in A { if int > 0 { hashSet.insert(int) while hashSet.contains(solution) { solution += 1 } } } return solution } |
感谢玛丽安的上述回答。
这是我使用python的解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | def solution(A): m = max(A) if m <= 0: return 1 if m == 1: return 2 # Build a sorted list with all elements in A s = sorted(list(set(A))) b = 0 # Iterate over the unique list trying to find integers not existing in A for i in xrange(len(s)): x = s[i] # If the current element is lte 0, just skip it if x <= 0: continue; b = b + 1 # If the current element is not equal to the current position, # it means that the current position is missing from A if x != b: return b return m + 1 |
得分100%/ 100%https://codility.com/demo/results/demoDCU7CA-SBR/
创建一个长度为N 1的二进制数组bin(C使用基于0的索引)
遍历二进制数组O(n)
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #include<stdio.h> #include<stdlib.h> #include<stdbool.h> int solution(int A[], int N) { // write your code in C99 (gcc 6.2.0) int i; bool *bin = (bool *)calloc((N+1),sizeof(bool)); for (i = 0; i < N; i++) { if (A[i] > 0 && A[i] < N+1) { bin[A[i]] = true; } } for (i = 1; i < N+1; i++) { if (bin[i] == false) { break; } } return i; } |
甜美的Swift版本。 100%正确
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | public func solution(inout A : [Int]) -> Int { //Create a Hash table var H = [Int:Bool]() // Create the minimum possible return value var high = 1 //Iterate for i in 0..<A.count { // Get the highest element high = A[i] > high ? A[i] : high // Fill hash table if (A[i] > 0){ H[A[i]] = true } } // iterate through possible values on the hash table for j in 1...high { // If you could not find it on the hash, return it if H[j] != true { return j } else { // If you went through all values on the hash // and can't find it, return the next higher value // e.g.: [1,2,3,4] returns 5 if (j == high) { return high + 1 } } } return high } |
PHP中的100%https://codility.com/demo/results/trainingKFXWKW-56V/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | function solution($A){ $A = array_unique($A); sort($A); if (empty($A)) return 1; if (max($A) <= 0) return 1; if (max($A) == 1) return 2; if (in_array(1, $A)) { $A = array_slice($A, array_search(1, $A)); // from 0 to the end array_unshift($A, 0); // Explanation 6a if ( max($A) == array_search(max($A), $A)) return max($A) + 1; // Explanation 6b for ($i = 1; $i <= count($A); $i++){ if ($A[$i] != $i) return $i; // Explanation 6c } } else { return 1; } } |
//说明
6a)将数组从值1拆分到末尾,并在第一个数字前加0
6b)如果array的最后一个元素的值是array的最大值,则该数组升序,因此我们返回max 1 //下一个正整数
6c)如果数组未升序,我们会通过以下函数找到一个缺失的数字:如果element的键不是该元素的值,但它应该是(A = [0 => 0,1 => 1,2 => 3,...]),我们返回键,因为我们期望键和值相等。
我的100/100解决方案
1 2 3 4 5 6 7 8 9 | public int solution(int[] A) { Arrays.sort(A); for (int i = 1; i < 1_000_000; i++) { if (Arrays.binarySearch(A, i) < 0){ return i; } } return -1; } |
此解决方案在测试中获得100/100:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | class Solution { public int solution(int[] A) { int x = 0; while (x < A.length) { // Keep swapping the values into the matching array positions. if (A[x] > 0 && A[x] <= A.length && A[A[x]-1] != A[x]) { swap(A, x, A[x] - 1); } else { x++; // Just need to increment when current element and position match. } } for (int y=0; y < A.length; y++) { // Find first element that doesn't match position. // Array is 0 based while numbers are 1 based. if (A[y] != y + 1) { return y + 1; } } return A.length + 1; } private void swap (int[] a, int i, int j) { int t = a[i]; a[i] = a[j]; a[j] = t; } } |
C的代码,实际上,它可以用于任何编程语言,而无需更改逻辑。
逻辑是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | int solution(int A[], int N) { // write your code in C99 long long sum=0; long long i; long long Nsum=0; for(i=0;i<N;i++){ sum=sum + (long long)A[i]; } if (N%2==0){ Nsum= (N+1)*((N+2)/2); return (int)(Nsum-sum); } else{ Nsum= ((N+1)/2)*(N+2); return (int)(Nsum-sum); } } |
这给出了100/100的得分。
这是我的解决方案,它的评估产率为88%-时间为O(n),正确性为100%,性能为75%。记住-可以包含所有负数或超过100,000的数字的数组。上面的大多数解决方案(带有实际代码)得分要低得多,或者根本不起作用。其他问题似乎与Codility上出现的Missing Integer问题无关。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | int compare( const void * arg1, const void * arg2 ) { return *((int*)arg1) - *((int*)arg2); } solution( int A[], int N ) { // Make a copy of the original array // So as not to disrupt it's contents. int * A2 = (int*)malloc( sizeof(int) * N ); memcpy( A2, A1, sizeof(int) * N ); // Quick sort it. qsort( &A2[0], N, sizeof(int), compare ); // Start out with a minimum of 1 (lowest positive number) int min = 1; int i = 0; // Skip past any negative or 0 numbers. while( (A2[i] < 0) && (i < N ) { i++; } // A variable to tell if we found the current minimum int found; while( i < N ) { // We have not yet found the current minimum found = 0; while( (A2[i] == min) && (i < N) ) { // We have found the current minimum found = 1; // move past all in the array that are that minimum i++; } // If we are at the end of the array if( i == N ) { // Increment min once more and get out. min++; break; } // If we found the current minimum in the array if( found == 1 ) { // progress to the next minimum min++; } else { // We did not find the current minimum - it is missing // Get out - the current minimum is the missing one break; } } // Always free memory. free( A2 ); return min; } |
可能会有所帮助,我正在使用算术级数计算总和,并使用二进制searach提取元素。用几百个值的数组检查效果很好。因为在2步中有一个for循环和迭代,所以O(n / 2)或更小
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | def Missingelement (A): B = [x for x in range(1,max(A)+1,1)] n1 = len(B) - 1 begin = 0 end = (n1)//2 result = 0 print(A) print(B) if (len(A) < len(B)): for i in range(2,n1,2): if BinSum(A,begin,end) > BinSum(B,begin,end) : end = (end + begin)//2 if (end - begin) <= 1 : result=B[begin + 1 ] elif BinSum(A,begin,end) == BinSum(B,begin,end): r = end - begin begin = end end = (end + r) if begin == end : result=B[begin + 1 ] return result def BinSum(C,begin,end): n = (end - begin) if end >= len(C): end = len(C) - 1 sum = n*((C[begin]+C[end])/2) return sum def main(): A=[1,2,3,5,6,7,9,10,11,12,14,15] print ("smallest number missing is",Missingelement(A)) if __name__ == '__main__': main() |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | static int spn(int[] array) { int returnValue = 1; int currentCandidate = 2147483647; foreach (int item in array) { if (item > 0) { if (item < currentCandidate) { currentCandidate = item; } if (item <= returnValue) { returnValue++; } } } return returnValue; } |