数组-重复的数字

150 阅读2分钟

数组是什么

有限个相同类型的变量组成的有序集合

声明

int[] arr;

初始化

//静态初始化
String[] strArr = {"","","",""};

//动态初始化
//默认值 null
String[] strArr = new String[4];
//默认值 0
int[] intArr = new int[4];

重复的数字

在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

来源:力扣(LeetCode)

集合法

遍历数组,利用 set 去重机制

public static int findRepeatNum() {
    int[] ints = {3, 2, 1, 1, 4, 5};
    Set<Integer> set = new HashSet<>();
    for (int value : ints) {
        if (!set.add(value)) {
            return value;
        }
    }
    return -1;
}

排序法

排序后相邻元素是否相等

public static int findRepeatNum() {
    int[] ints = {3, 2, 1, 1, 4, 5};
    Arrays.sort(ints);
    for (int i = 1; i < ints.length; i++) {
        if (ints[i - 1] == ints[i]) {
            return ints[i - 1];
        }
    }
    return -1;
}

临时数组法

初始化一个长度为 n 的临时数组 temp,遍历目标数组,temp[target[i]] 赋值 1,temp[target[i]] != 0 时表示存在重复数字

public static int findRepeatNum() {
    int[] ints = {3, 2, 1, 1, 4, 5};
    int[] temp = new int[ints.length];
    for (int value : ints) {
        if (temp[value] != 0) {
            return value;
        }
        temp[value] = 1;
    }
    return -1;
}

交换位置法

遍历数组,target[i] != i 时,交换 target[i] 和 target[target[i]],发生交换时继续遍历当前位置,i-- 抵消 i++ 实现继续遍历当前位置

public static int findRepeatNum() {
    int[] ints = {3, 2, 1, 1, 4, 5};
    for (int i = 0; i < ints.length; i++) {
        if (i == ints[i])
            continue;
        int index = ints[i];
        int temp = ints[index];
        if (temp == ints[i]) {
            return ints[i];
        }
        ints[index] = ints[i];
        ints[i] = temp;
        i--;
    }
    return -1;
}

取反法

遍历数组,target[target[i]] 取反,当 target[target[i]] 为负数时表示重复数字

public static int findRepeatNum() {
    int[] ints = {3, 2, 1, 1, 4, 5};
    for (int i = 0; i < ints.length; i++) {
        int index = Math.abs(ints[i]);
        if (ints[index] < 0) {
            return Math.abs(ints[i]);
        }
        ints[index] = -ints[index];
    }
    return -1;
}