我从Codility的代码测试练习中得到以下问题:
给出了由N个不同整数组成的零索引数组A.该数组包含[1 ..(N + 1)]范围内的整数,这意味着只缺少一个元素。
您的目标是找到缺少的元素。
写一个函数:
class Solution {public int solution(int [] A); }
给定零索引数组A,返回缺少元素的值。
例如,给定数组A使得:
A [0] = 2 A [1] = 3 A [2] = 1 A [3] = 5
该函数应该返回4,因为它是缺少的元素。
假设:
N是[0..100,000]范围内的整数; A的元素都是截然不同的; 数组A的每个元素是[1 ..(N + 1)]范围内的整数。
复杂度:
预期的最坏情况时间复杂度为O(N); 预期的最坏情况空间复杂度为O(1),超出输入存储(不包括计算输入参数所需的存储空间)。
可以修改输入数组的元素。
我的方法是将给定数组转换为ArrayList,使用ArrayList查找数组中的最低和最高值,并从最低到最高迭代所有可能的值,然后返回缺失值。
这解决了示例问题,但我的问题似乎是在给定数组的以下条件下我无法得到正确的答案:
“空列表和单个元素”
“缺少第一个或最后一个元素”
“单一元素”
“两个要素”
我做错了什么,解决这个问题的正确方法是什么?
答案 0 :(得分:16)
这个问题有一个数学解决方案,基于sum of consecutive integers from 1 to n is equal to n(n+1)/2
的事实。
使用此公式,我们可以计算1 to N+1
的总和。然后,O(N)
时间复杂度,我们计算数组中所有元素的实际总和。
完整和实际总数之间的差异将产生缺失元素的值。
空间复杂度为O(1)
。
答案 1 :(得分:2)
问题陈述明确指出数组将由“N个不同的整数”组成,因此N必须至少为2. N = 0且N = 1如果我们用英语写它们就没有意义,例如“由0个不同整数组成的数组......”。
给出了由N个不同整数组成的零索引数组A.该数组包含[1 ..(N + 1)]范围内的整数,这意味着只缺少一个元素。
根据这些初始条件和陈述的假设,“单一元素”,“空列表”等测试是完全不合适的。
正确的生产代码很可能必须测试无效条件,但这不是挑战的既定目标。
答案 2 :(得分:2)
另一个100%的解决方案:
实际上甚至不需要使用64位整数来避免一些测试试图触发的溢出(在编写时阵列大小为100000的那些)。而你只能使用一个和变量。最后一行通过不同地实现n(n + 1)/ 2来避免溢出,因此除以2的除法发生在“早期”:
C#:
class Solution {
public int solution(int[] A) {
var sum = 0;
for(int i = 0; i < A.Length; i++)
sum += A[i];
return A.Length % 2 == 0 ? -sum + (A.Length/2 + 1) * (A.Length+1)
: -sum + (A.Length/2 + 1) * (A.Length+2);
}
}
答案 3 :(得分:1)
Golang解决方案:
func Solution(A []int) int {
n := len(A) + 1
total := n * (n + 1) /2
for _, e := range A {
total -= e
}
return total
}
答案 4 :(得分:1)
这是使用JavaScript的另一种解决方案,经过100%测试。
function solution(A) {
let maximumNumber = A.length + 1;
let totalSum = (maximumNumber*(maximumNumber + 1))/2;
let partialSum = 0;
for(let i=0; i<A.length; i++) {
partialSum += A[i];
}
return totalSum - partialSum;
}
答案 5 :(得分:1)
我在Java中的解决方案100% 检测到的时间复杂度: O(N)
import java.util.*;
class Solution {
public int solution(int[] arr) {
if(arr.length == 0) return 1;
int sumArr = 0;
for(int i=0; i < arr.length; i++){
sumArr = sumArr + arr[i];
}
int sumN = 0;
for(int i=1; i <= arr.length+1; i++){
sumN = sumN + i;
}
if(sumArr == sumN) return arr.length;
return sumN - sumArr;
}
}
答案 6 :(得分:0)
我认为最好的方法是通过 XOR,它干净、优雅且快速。不需要数学知识,只需要CS!与其他总结方式相比,这还有另一个优势,因为我们只是在进行按位运算,因此不会出现整数溢出。
时间上的 O(n),空间上的 O(1)。
代码如下(Javascript),只需要一个循环:
function solution(A) {
// write your code in JavaScript (Node.js 8.9.4)
let missingNumber = A.length + 1;
// Sum up 1+2+3+...+N+(N+1) AND all of A[i] (except value not present in A[i] obviously). The value not present in A[i] is the odd one out. Note `missingNumber` starts with `A.length + 1` (i.e. N+1) because we loop N times here only...
for(let i = 0; i < A.length; ++i) {
missingNumber ^= (i + 1) ^ A[i];
}
return missingNumber;
}
https://florian.github.io/xor-trick/ 对理解 XOR 有很好的指导作用。
基本上采用 X ^ X equals 0
的想法,我们使用它来利用重复值抵消值,以便我们得到非重复值(即剩下的缺失元素)。
这是有效的,因为问题约束保证 the elements of A are all distinct
。所以我们可以将它们组合在一起来利用这个技巧。如果这是一个可以复制元素的排列,这不起作用,即 PermCheck
答案 7 :(得分:0)
附上用 kotlin 编写的解决方案:
fun solution(A: IntArray): Int {
val lastElement = A.size + 1
// including missing element
val arraySize = A.size + 1L
var result = (arraySize * (1 + lastElement)) / 2
A.forEach {
result -= it
}
return result.toInt()
}
附言使用了 Arithmetic progression sum formula。
P.P.S.使用 Long
原始类型执行操作,因为您可能面临一些 Int
限制。
答案 8 :(得分:0)
java 解决方案:
public int solution(int[] A) {
int nExpected = A.length + 1;
long seriesSumExpected = nExpected * (nExpected + 1L) / 2;
long seriesSum = getSum(A);
return (int) (seriesSumExpected - seriesSum);
}
private long getSum(int[] A) {
long sum = 0L;
for (int i : A) {
sum += i;
}
return sum;
}
任务得分:100%
正确性:100%
性能:100%
答案 9 :(得分:0)
这是我的解决方法。
const assert = require("assert").strict;
function solution(A) {
const n = A.length + 1;
const sum = (n * (n + 1)) / 2;
const sum2 = A.reduce((a, b) => a + b, 0);
return sum - sum2;
}
assert.strictEqual(solution([2, 3, 1, 5]), 4);
assert.strictEqual(solution([]), 1);
assert.strictEqual(solution([1]), 2);
答案 10 :(得分:0)
Java解决方案:
// Import Dependencies
import java.util.*;
class Solution {
public int solution(int[] A) {
// write your code in Java SE 8
long N = A.length+1;
long realSum = N*(N+1)/2;
long foundSum = 0;
for(int i=0;i<N-1;i++){
foundSum = foundSum + A[i];
}
long answer = (realSum - foundSum);
return (int)(answer);
}
}
答案 11 :(得分:0)
快速解决方案100%通过
import Foundation
import Glibc
public func solution(_ A : inout [Int]) -> Int {
let sortedArray = A.sorted(by: { $0 < $1 })
for i in 0..<sortedArray.count {
if sortedArray[i] != i+1 {
return i+1
}
}
return A.count + 1
}
答案 12 :(得分:0)
using System;
// you can also use other imports, for example:
// using System.Collections.Generic;
// you can write to stdout for debugging purposes, e.g.
// Console.WriteLine("this is a debug message");
class Solution {
public int solution(int[] A) {
// write your code in C# 6.0 with .NET 4.5 (Mono)
int i, j = 0, n = A.Length;
if (A != null && n != 0)
{
Array.Sort(A);
for (j = A[0], i = 0; i < n; i++, j++)
{
if (j == A[i]) continue;
else return j;
}
if (i == n) return (A[0] == 2) ? 1 : ++A[--n];
}
else return 1;
return -1;
}
}
答案 13 :(得分:0)
我对此感到麻烦,但这仅仅是因为我不了解所有情况。 这是我在Java中的解决方案。稍长一点(我不能缩小),但是分数是100%。
class Solution {
public int solution(int[] A) {
Arrays.sort(A);
if (A.length == 1) {
if (A[0] == 1) {
return A.length + 1;
} else {
return A[0] - 1;
}
}
for (int n = 0; n < A.length - 1; n++) {
if (A.length == 2) {
if (A[n] == 1) {
if (A[n] + 1 != A[n + 1]) {
return A[n] + 1;
}
return A.length + 1;
} else {
return 1;
}
} else {
if (A[0] != 1) {
return 1;
}
if (A[n] + 1 != A[n + 1]) {
return A[n] + 1;
}
}
}
return A.length + 1;
}
}
分析摘要 该解决方案获得了满分。
向内纳德致敬
答案 14 :(得分:0)
Ruby,100%通过:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
答案 15 :(得分:0)
我使用此Java代码作为解决方案。得到了100%
class Solution {
public int solution(int[] A) {
int result = 0;
Set<Integer> set = new HashSet<>();
for (int x : A) {
set.add(x);
}
for (int x = 1; x < set.size() + 2; x++) {
if (!set.contains(x)) {
return x;
}
}
return result;
}
}
答案 16 :(得分:0)
您可以使用Array首先对元素进行排序,然后使用simple for循环对其进行迭代,并找到缺少的值。
这是我的简单代码,其中检测到的时间复杂度为O(N)
或O(N * log(N))
(在Codility中)。
public static int solution(int[] A) {
int size = A.length;
int count = 1;
Arrays.sort(A);
for (int i = 0; i < size; i++) {
if (A[i] != count)
return count;
count++;
}
return count;
}
答案 17 :(得分:0)
尽管现在连续整数的总和将有助于获得快速的解决方案,但使用额外的数组和2O(N)复杂度而不计算总和可能是一种快速但不具有内存效率的解决方案。
这是我的解决方法:
class Solution {
public int findFalse(boolean [] ar){
for (int j = 0; j<ar.length; ++j){
if(ar[j]==false){
return j;
}
}
return -1;
}
public int solution(int[] A) {
// write your code in Java SE 8
boolean [] M = new boolean[A.length+1];
for (int i:A){
M[i-1] = true;
}
int missingValue = findFalse(M) +1 ;
return missingValue;
}
}
答案 18 :(得分:0)
这获得了100%的Codality。它使用非常基本的数学。对于数组: {2,3,1,5} 1,2,3,4,?
public int solution(int A[]) {
if (A == null) return 0;
if(A.length == 0) return 1;
int total = 0;
int max = A.length + 1;
for (int i = 0; i < A.length; i++) {
total += A[i];
max += i + 1;
}
return (max - total) < 0 ? 0 : (max - total);
}
这是我不得不抬头的一件事,尽管这让我很烦,但我不明白。
if(A.length == 0) return 1;
这使IMO毫无意义。如果数组长度为零,则IMO应为零。
答案 19 :(得分:0)
// Solution with LinQ.
// Task Score: 100%
// Correctness: 100%
// Performance: 100%
using System.Linq;
public static int GetPermMissingElem(int[] A)
{
if (A.Length <= 0)
return 1;
int size = A.Length;
System.Collections.Generic.List<int> missing = Enumerable.Range(1, A[size - 1]).Except(A.ToList()).ToList();
if (!missing.Any())
return A[size -1] + 1;
return missing.First();
}
答案 20 :(得分:0)
Swift 4
中的100%解决方案:
public func solution(_ A : inout [Int]) -> Int {
// first we simply calculate the sum on the given array
var sum = 0
for element in A {
sum += element
}
// as the sum of consecutive ints is given by n(n+1)/2,
// we calculate the expected sum from 1 to n + 1
// (which is ((n+1)(n+2))/2) and substract the actual sum
// to get the missing element
return ((A.count + 1) * (A.count + 2) / 2) - sum
}
答案 21 :(得分:0)
这是PHP中使用从1到n的连续整数之和等于n(n + 1)/ 2的解决方案。
function solution($A) {
$size = count($A) + 1;
$total = ($size * ($size + 1)) / 2;
return $total - array_sum($A);
}
答案 22 :(得分:0)
此问题是“时间复杂性”课程的一部分。
https://codility.com/media/train/1-TimeComplexity.pdf
实际上,最后有解释如何在不进行任何循环的情况下计算数组中元素的总和。
这是Python3中的最终解决方案:
def solution(A):
n = len(A)+1
result = n * (n + 1)//2
return result - sum(A)
答案 23 :(得分:0)
目标C解决方案O(N)-XOR方法
Codility提供的结果
任务得分:100%
正确性:100%
效果:100%
时间复杂度
最差的时间复杂度是O(N)或O(N * log(N))
+(int)XORSolution:(NSMutableArray*)array {
/******** Algorithm Explanation ********/
// FACTS
// Use of XOR operator
// Edge case: when the array is empty [], we should return 1
// XOR of a number with itself is 0.
// XOR of a number with 0 is number itself.
// STEP 1
// XOR all the array elements, let the result of XOR be X1.
// STEP 2
// XOR all numbers from 1 to n, let XOR be X2.
// STEP 3
// XOR of X1 and X2 gives the missing number.
int n = (int)[array count];
// Edge Case
if(n==0){
return 1;
}
else {
// STEP 1
/* XOR of all the elements in array */
int x1 = 0;
for (int i=0; i<n; i++){
x1 = x1 ^ [[array objectAtIndex:i]intValue];
}
// STEP 2
/* XOR of all the elements from 1 to n+1 */
int x2 = 0;
for (int i=1; i<=(n+1); i++){
x2 = x2 ^ i;
}
// STEP 3
int missingElement = x1 ^ x2;
return missingElement;
}
}
答案 24 :(得分:0)
目标C解决方案O(N)-SET方法
Codility提供的结果
任务得分:100%
正确性:100%
效果:100%
时间复杂度
最差的时间复杂度是O(N)或O(N * log(N))
+(int)SETSolution:(NSMutableArray*)array {
/******** Algorithm Explanation ********/
// FACTS
// Use of a NSSet to verify if the missing element exist or not.
// Edge case: when the array is empty [], we should return 1
// STEP 1
// validate the edge case
// STEP 2
// Generate a NSSet with the array elements in order to search an element faster
// STEP 3
// Use a for loop and find the current 'i' in the NSSset
// If an elements doesn't exist in the NSSet, that means it's the missing element.
int n = (int)[array count];
int missing = 0;
// STEP 1
if (n == 0) {
missing = 1;
return missing;
}
else {
// STEP 2
NSSet *elements = [NSSet setWithArray:array];
// STEP 3
for (int i = 1; i <= (n+1); i++) {
// O(N) or O(N * log(N)) depending of required iterations
if (![elements containsObject:[NSNumber numberWithInt:i]]) {
missing = i;
return missing;
}
}
return missing;
}
}
答案 25 :(得分:0)
虽然我看重数学解决方案,但它并不那么容易理解。
因此,这是一个简单的解决方案,其Codility得分为100%。
import java.util.*;
public int solution(int[] A) {
int missing = 1; // missing number 1 already
Arrays.sort(A);
// check numbers one by one
for (int i = 0; i < A.length; i++) {
if (A[i] == missing) { // we found the missing number !
missing = A[i]+1; // add +1 and keep checking
}
}
return missing;
}
答案 26 :(得分:0)
private static int getMissingElementInArrayNew(int[] A) throws IOException {
double n = A.length + 1;
double totalSum = (double) ((n * (n + 1)) / 2);
for (int i = 0; i < A.length; i++) {
totalSum -= A[i];
}
return (int) (totalSum == 0 ? A.length + 1 : totalSum);
}
答案 27 :(得分:-1)
这是我的代码,也是100%的结果:
class Solution {
public int solution(int[] A) {
// write your code in Java SE 8
int value = A.length;
Arrays.sort(A);
if (value == 0) return 1;
if (value == 1) {
if ( A[0] == 1 ) {
return A[0] + 1;
}
else {
return A[0] - 1;
}
}
for (int x = 1; x <= value; ++x) {
if ( A[x - 1] != x ) {
return x;
}
}
return A[value - 1] + 1;
}
}
答案 28 :(得分:-1)
我在C#中尝试了这个解决方案,并在100%中得分100%
https://codility.com/programmers/lessons/3-time_complexity/perm_missing_elem/
class Solution
{
public int solution(int[] A)
{
long sum = 0, sum1 = 0;
int i;
for (i = 0; i < A.Length; i++)
{
sum += Convert.ToInt64(i + 1);
sum1 += Convert.ToInt64(A[i]);
}
sum += Convert.ToInt64(i+1);
return Convert.ToInt32(sum - sum1);
}
}