剑指offer打卡 JZ3

在牛客网刷的,还是跟leetcode一样非acm模式,由于急着暑期实习题量不固定,八股算法轮刷

打卡内容偏个人笔记,本人水平一般(代码随想录稀里糊涂刷了一遍),从小白开始分析(甚至会分析语法),尽量一题多解深入探究(一般ac后看看前三个题解发散下思维),希望能对你有帮助

JZ3 数组中重复的数字

描述

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

分析

首先暴力解法外层for循环和内层for循环匹配到一样的元素肯定可以实现

接下来由于空间复杂度O(n) ,数据范围:0≤n≤10000 ,可以用数组实现一个哈希表,扫描一遍输入数组后得到是否重复的信息,不合法的输入的话输出-1就直接在处理完逻辑后return -1,直接ac了,当然代码可以在第一个for循环里更新hash后马上判断,代码简洁且更快return(在循环里多点语句,能一个循环解决就放一起)

public int duplicate(int[] numbers) {
    int[] hash = new int[10010];
    for (int i = 0; i < numbers.length; i++) {
        hash[numbers[i]]++;
    }
    for (int i = 0; i < hash.length; i++) {
        if (hash[i] >= 2) {
            return i;
        }
    }
    return -1;
}

看了题解想起来可以用集合HashSet,顺便复习了范型

Set hash = new HashSet();和Set<Integer> hash = new HashSet<>();的区别:

在Java 1.5版本之前,泛型并不是Java语言的一部分,所以可以直接使用 Set 而不需要指定泛型类型。但是这种方式在Java 1.5版本之后就被认为是不推荐的,因为它会导致编译器无法进行类型检查,可能会引发类型安全问题。

Set<Integer> hash = new HashSet<>(); 这行代码中通过使用泛型指定了 HashSet 中元素的类型为 Integer。这种方式是更加安全和推荐的写法,因为编译器会进行类型检查,可以在编译时捕获类型错误。

使用HashSet的代码如下,先判断Set中是否存在,不存在就加入(if下面的代码自带else逻辑)

public int duplicate(int[] numbers) {
    Set<Integer> hash = new HashSet<>();
    for (int i = 0; i < numbers.length; i++) {
        if (hash.contains(numbers[i])) {
            return numbers[i];
        }
        hash.add(numbers[i]);
    }        
    return -1;
}

看了题解发现这道题可以边遍历变=边替换,通过把不符合的交换维护numbers[i] = i,因为数组中的元素范围是 0 到 n-1,所以如果数组中没有重复数字,那么当数组排序后,数字 i 将出现在下标为 i 的位置上。如果有重复数字,则会被检测到。

  • 在交换数字后,可能会出现新的数字出现在原本的位置上,所以需要在交换后重新检查该位置。
  • 为了实现这一点,在交换后将当前索引 i 减一,使得下次循环重新检查当前位置。
public int duplicate(int[] numbers) {
    for (int i = 0; i < numbers.length; i++) {
        if (numbers[i] != i) {
            if (numbers[i] == numbers[numbers[i]]) 
                return numbers[i];
            int temp = numbers[numbers[i]];
            numbers[numbers[i]] = numbers[i];
            numbers[i] = temp;
            i--; // 遍历完0位元素以及交换完数字后,如果0位元素仍不符合数组存放原则:numbers[i] = i,那么还要重新遍历0位元素
        }
    }
    return -1;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值