zoukankan      html  css  js  c++  java
  • 寻找缺失的那个数

    在网上看到几个类似的寻找缺失/重复元素的面试题,总结起来有两类:

    1. 有N个整数组成的数组,数组中每个整数n:1<=n<=N,并且仅出现一次,其中有一个数出现了2次或者缺失了某一个数,求这个数是多少?

    2. 有N个整数组成的数组,数组中每个整数n:1<=n<=N,并且仅出现一次,其中只有一个n1是重复的,即出现了两次,而有一个整数n2不在数组中,求这两个数;可以推而广之,比如有两个数重复出现两次,另外有一个不在数组中,求这三个数等等

    基本要求一般是:线性时间复杂度,尽可能小的空间复杂度

    这种题目的本质就是:标准(一个都不缺,一个都不多)结果我们知道,现状我们知道,要做的就是找到那个引起现状跟标准不一致的元素,这个元素对结果的影响可能有直接的因果关系(比如第一题),或者间接的因果关系(比如第二题)

    先做个定义:

    1. 标准数组:一个都不多,一个都不少的数组,即【1,2,3,...N】

    2. 当前数组:需要从中找出坏分子的当前数组

    通过对标准的不同理解,可以得出不同的解法:

    第一种标准:hash签名,签名的意义就是为数组计算一个标识符,然后将实际数组的标识符和标准数组的标识符比较,得出结论。

    hash函数的设计可以是:

    1. 以十进制为形式,比如求和:对第一题来说,直接求标准数组的和 与 当前数组的和之差 就可以解决。对第二题,因为我们要找到两个坏分子,所以一个hash函数已经不够了,需要再设计一个hash函数,比如平方和,立方和,连乘等都可以。然后通过方程组求解;如果需要找到三个坏分子呢,则需要设计第三个hash函数。

    2. 以二进制为形式,比如XOR:本质上跟求和是类似的,但是从hash的角度来说,则是一种不同的hash算法。对第一题来说,直接求标准数组的XOR 与 当前数组的XOR 最后再将结果XOR一次就可了。对第二题来说,第二个hash函数就不太好设计了,因为要从二进制的角度考虑方程组求解的问题,这个我不太习惯。比如第二个hash设计成逻辑与,我们得到【X XOR Y = ?; X ^ Y = ??】,计算的时候恐怕还是比较麻烦的事情。

    第二种标准:正确的排列,即如果对于标准数组,其第N个位置的上的值应该就是N,对于非标准数组,则可能是2*N(重复)或者0(缺失)

    排列的构造方式可以是:

    1. 在原数组上排序:时间复杂度nlog(n),空间复杂度为o(1)

    2. 在原数组上通过exchange元素的方式调整,时间复杂度nlog(n),空间复杂度o(1)

    一旦构造好标准数组的排列,则通过比较标准数组的排列和非标准数组的排列就可以找到坏分子。

    对于上面的第二题,还有人用DP的思想,主要想法就是将第二题拆分成类似第一题的场景,然后再解。

    稍微描述的详细一点是:

    1. 二分当前数组

    2. 通过上面的两个标准的某个方法来判断坏分子在左边的数组还是在右边的数组,如果在都在左半数组,则接下来继续二分左半数组;否则都在右半数组,则继续二分右半数组;

    3. 如果一个在左半数组,一个在右半数组,则该问题变成了第一题的场景,可以顺利得解。

    如果将第二题扩展成要找到3个坏分子,则上面的DP也是可以解的。

    上面的一些整理是基于(http://groups.google.com/group/pongba/browse_thread/thread/57db0afcd8aac08d)

    上面说明了类似“通过标准和现状的差距求解”算法的个人思路,抽象的未必正确,欢迎指正。

  • 相关阅读:
    nginx 阻止ip访问
    mysql sql语句性能分析
    SWFUpload demo
    XSHELL win7 和 linux 系统之间文件互传
    基于HTTP协议的轻量级开源简单队列服务:HTTPSQS
    The following packages have been kept back
    php 错误日志记录
    TWIG 分页宏(基于 bootstrap)
    gitconfig 全局配置文件。
    简单的图片异步上传代码
  • 原文地址:https://www.cnblogs.com/raymondshiquan/p/2108150.html
Copyright © 2011-2022 走看看