剑指offer 面试题51 数组中重复的数字

来源:互联网 发布:Linux mmap 文件复制 编辑:程序博客网 时间:2024/06/07 20:46

剑指offer 面试题51 数组中重复的数字

在一个长度为 n 的数组里的所有数字都在 0 到 n-1 的范围内。
数组中某些数字是重复的,但不知道有几个数字重复了,也不知道
每个数字重复了几次。请找出数组中任意一个重复的数字。例如,
如果输入长度为 7 的数组 {2, 3, 1, 0, 2, 5, 3},那么对应
的输出是重复的数字 2 或者 3。

package algorithm.foroffer.top60;import org.junit.Test;import java.util.Arrays;/** * description: * * @author liyazhou * @create 2017-06-05 21:43 * 面试题 51:数组中重复的数字 * * 题目: *      在一个长度为 n 的数组里的所有数字都在 0 到 n-1 的范围内。 *      数组中某些数字是重复的,但不知道有几个数字重复了,也不知道 *      每个数字重复了几次。请找出数组中任意一个重复的数字。例如, *      如果输入长度为 7 的数组 {2, 3, 1, 0, 2, 5, 3},那么对应 *      的输出是重复的数字 2 或者 3。 * * 考查点: * * 思路: *      1. 方法一: *          时间复杂度小,需要辅助空间 *          需要一个保存数字以及其出现次数的 map *      2. 方法二: *           时间复杂度高,空间复杂度是 O(1) *           两层循环遍历所有的数字 * */public class Test51 {    public int findOneDuplicateDigit(int[] array){        if (array == null || array.length == 0) throw new RuntimeException("Invalid input.");        // Map<Integer, Integer> map = new HashMap<>();        int[] entrys = new int[array.length];        int result = -1;        for (int i = 0; i < array.length; i++){            entrys[array[i]] += 1;            if (entrys[array[i]] > 1) {                result = array[i];                break;            }        }        System.out.println(Arrays.toString(entrys));        return result;    }    public int findOneDuplicateDigit2(int[] array){        if (array == null || array.length == 0) throw new RuntimeException("Invalid input.");        int result = -1;        for (int i = 0; i < array.length; i ++){            for (int j = i+1; j < array.length; j ++){                if (array[i] == array[j]) return array[i];            }        }        return result;    }    @Test    public void test(){        int[] array = {1, 2, 3, 5, 7, 2, 1, 3};        System.out.println(findOneDuplicateDigit(array));        System.out.println(findOneDuplicateDigit2(array));    }}

更加高效的解法。
思路如下:
从头到尾遍历每一个数字,将以当前数字为下标的元素加 length,
当再次有跟这个下标一样的数字出现时,发现该下标处的元素大于 n-1,则这个数字出现了两次。

一个疑问,当被遍历到的数字大于length呢?
说明它的下标跟之前的数字相等,因此它的值被加 length。这是一个编码过程。
现在需要它的真实值,只需要 减去 length就可以得到它的原始值。

// Parameters://    numbers:     an array of integers//    length:      the length of array numbers//    duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;//                  Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++//    这里要特别注意~返回任意重复的一个,赋值duplication[0]// Return value:       true if the input is valid, and there are some duplications in the array number//                     otherwise falsepublic boolean duplicate(int numbers[],int length,int [] duplication) {    duplication[0] = -1;    boolean valid = false;    if (numbers == null) return valid;    for (int i = 0; i < length; i ++){        int index = numbers[i];        if (index >= length)    // index 要表示原来数组中i位置处的元素            index -= length;        if (numbers[index] > length){    // numbers[index]已经被一个同样的值为index的元素修改过            valid = true;            duplication[0] = index;            break;        }        numbers[index] += length;    }    return valid;}
阅读全文
1 0