【算法】0~n-1中缺失的数字

12 篇文章 0 订阅

剑指 Offer 53 - II. 0~n-1中缺失的数字

https://leetcode-cn.com/problems/que-shi-de-shu-zi-lcof/

数学法

 递增的等差数列之和为n*(n-1)/2,n是元素个数,数组之和可以求到,它们的差就是要找的数字

class Solution {

    /**
     * @param Integer[] $nums
     * @return Integer
     */
    function missingNumber($nums) {
        //count($nums)比真实元素个数少1
    	return count($nums)*(count($nums)+1)/2 - array_sum($nums);
    }
}

但很显然这并不是最优解,不说复杂度问题,单凭它需要算全部的数值之和很可能导致内存溢出就说明它是不安全的(虽然本题指定的范围不会导致溢出,但仍然不推荐这样写)。

顺序查找

如果不跳,每个下标与其数值正好是对应的...

    function missingNumber($nums) {
        if($nums==[0]){
    		return 1;
    	}
    	for($i=0;$i<count($nums);$i++){
    		if($nums[$i] != $i){
    			return $i;
    		}
    	}
        return $i;
    }

与其类似的还有两个相邻元素之和、之差求法

但这些都是线性遍历数组,在排序数组中找一个数字,二分查找也可。 

时间O(n),空间O(1)

二分查找

如何确定缺省值在左边还是右边?从之前观察到的规律可以知道,如果没有缺省,$nums[$i]==$i应该成立,一旦$nums[$i]<$i,说明出现了缺省

class Solution {

    /**
     * @param Integer[] $nums
     * @return Integer
     */
    function missingNumber($nums,$left=0,$right=-1) {
    	if($right==-1){
    		$right = count($nums)-1;
    	}
    	while($left < $right){
    		$mid = intval(($left+$right)/2);
    		if($nums[$mid] == $mid){
    			return $this->missingNumber($nums,$mid+1,$right);
    		}else{
    			return $this->missingNumber($nums,$left,$right-1);
    		}
    	}
    	return $nums[$right]==$right ? $right+1 : $right;
    	
    }
}

 二分查找的时间复杂度,最优情况下是每次真的能在最中间分开,那么每次要找的数组范围就是n、n/2、n/4...,{2}^x=n,x=log({2}^n) ,即O(log({2}^n)) .本例中几乎是等差数列,恰好就是二分查找的最优情况。

二分查找在最差情况下退化为普通的遍历,O(n),本例不会出现此情况。

O(log(n)),但是空间复杂度需要n+n/2+n/4...=2/3n,O(n)级别,与前面顺序查找的O(1)相比是非常典型的空间换时间方式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值