数学与数字6:LeetCode268. 丢失的数字
Posted 纵横千里,捭阖四方
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数学与数字6:LeetCode268. 丢失的数字相关的知识,希望对你有一定的参考价值。
算法学习的一个原则是”复杂问题简单做,简单问题深入做“,这是一道简单的问题,但是可以深入分析。我们参考宫水三叶等的文章,发现这个题竟然有5种做法。
先看题意:
给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。
示例:
输入:nums = [3,0,1]
输出:2
解释:n = 3,因为有 3 个数字,所以所有的数字都在范围 [0,3] 内。2 是丢失的数字,因为它没有出现在 nums 中。
题目没有说数组是否为排序的,那我们就要按照无序来处理。
首先想到的是排序一下再找nums[i]==i,不相等的地方就是答案。
class Solution
public int missingNumber(int[] nums)
int n = nums.length;
Arrays.sort(nums);
for (int i = 0; i < n; i++)
if (nums[i] != i) return i;
return n;
第二种自然是hash,利用 nums 的数值范围为 [0,n],且只有一个值缺失,我们可以直接开一个大小为 n+1 的数组充当哈希表,进行计数,没被统计到的数值即是答案。
class Solution
public int missingNumber(int[] nums)
int n = nums.length;
boolean[] hash = new boolean[n + 1];
for (int i = 0; i < n; i++) hash[nums[i]] = true;
for (int i = 0; i < n; i++)
if (!hash[i]) return i;
return n;
第三种是算出总和再作差,这种思想在解决很多无序的数字问题时都可以用到。
利用 nums 的数值范围为 [1,n],我们可以先计算出 [1,n] 的总和sum(利用等差数列求和公式),再计算nums 的总和cur,两者之间的差值即是nums 中缺失的数字。
class Solution
public int missingNumber(int[] nums)
int n = nums.length;
int cur = 0, sum = n * (n + 1) / 2;
for (int i : nums) cur += i;
return sum - cur;
第四种方式是异或,找缺失数、找出现一次数都是异或的经典应用。这种思想在找重复数字时也会遇到的。
我们可以先求得 [1,n] 的异或和 ans,然后用 ans 对各个 nums[i] 进行异或。
这样最终得到的异或和表达式中,只有缺失元素出现次数为 1 次,其余元素均出现两次(x ⊕x = 0),即最终答案 ans 为缺失元素。
class Solution
public int missingNumber(int[] nums)
int n = nums.length;
int ans = 0;
for (int i = 0; i <= n; i++) ans ^= i;
for (int i : nums) ans ^= i;
return ans;
第五种,其实上面第一种我们可以进一步深入做,那就是将上面的for循环该成二分查找,根据nums[i]与i的大小情况来决定向左还是向右折半。感兴趣的同学可以研究一下。
以上是关于数学与数字6:LeetCode268. 丢失的数字的主要内容,如果未能解决你的问题,请参考以下文章
Leetcode刷题100天—268. 丢失的数字(哈希表)—day14
LeetCode:268. 丢失的数字1404. 将二进制表示减到 1 的步骤数