您的位置:首页 > 其它

LeetCode - 268. Missing Number

2016-07-02 20:35 405 查看
一开始想到的思路是使用和来计算,首先我们通过公式将从1到n的和计算出来,因为给出的数组中少了一个元素,所以我们再计算一下给出的数组的和,用1到n的和减去给出的数组的和,就得到了结果。时间复杂度为O(n),代码如下:

public class Solution {
public int missingNumber(int[] nums) {
if(nums == null || nums.length == 0) return 0;

int n = nums.length;
int sumAll = n * (n + 1) / 2;
int sum = 0;

for(int i = 0; i < nums.length; i++){
sum += nums[i];
}

return sumAll - sum;
}
}

第二种方式是使用位运算中的XOR运算,在以前single number那道题目中我们就使用过这种方法,只是这里使用得更加巧妙,在迭代整个数组的过程中,我们不断地对index i和nums[i]进行XOR运算,在循环退出之后再和nums.length进行XOR运算就得到了结果。这里我们使用一个例子来看一下算法的运算过程:

0 1 2 4 5 6 7

0 1 2 3 4 5 6

可见如果再加上一个nums.length的话,所有的数字中除了missing number之外都是成对的,正好使用XOR全部消除掉,最后得到missing number,时间复杂度O(n),代码如下:

public int missingNumber(int[] nums) {

int xor = 0, i = 0;
for (i = 0; i < nums.length; i++) {
xor = xor ^ i ^ nums[i];
}

return xor ^ i;
}


第三种方法是使用二分搜索,这里要注意对二分搜索中条件的设置是nums[mid] > mid,在这种情况下说明missing number在mid指向的部分里,比如上面例子所示,也就是mid指针在index 3 4 5 6上面,这时要把right指针新设置为mid,所以在退出循环前面的一步必然是left++,结合二分搜索的判断条件,最后返回left即可。如果给出的数组是已排序的,那么时间复杂度为O(logn),如果是没有排序的,那么时间复杂度为O(nlogn),代码如下:

public int missingNumber(int[] nums) { //binary search
Arrays.sort(nums);
int left = 0, right = nums.length, mid= (left + right)/2;
while(left<right){
mid = (left + right)/2;
if(nums[mid]>mid) right = mid;
else left = mid+1;
}
return left;
}

思考:

1. 这道题目的第三种方法更加体现出了二分搜索作为一种思想而不是单单作为一种查找数字的方法的力量,使用二分搜索这种思想,可以根据题目的要求在二分搜索的模板上进行任意的修改,包括对条件判断的修改,可以省区if(nums[mid] == target)的情况和修改left/right指针移动的情况,非常强大。另外也要根据指针的移动情况正确判断出跳出循环时left指针和right指针所在位置的情况,从而拿出正确的返回值
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息