剑指 Offer 03. 数组中重复的数字

这篇博客介绍了三种不同的方法来找出数组中重复的数字。第一种是利用HashSet,遍历数组并检查元素是否已存在;第二种是通过排序将元素归位,找到不匹配的位置;第三种是转换数组为链表并使用快慢指针找环。每种方法都有其独特之处,适用于不同的场景。
摘要由CSDN通过智能技术生成

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

示例 1:

输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3 
 

题解:


题解1:Set

Set是元素无序,不可重复的集合
使用HashSet来解决这道题目
遍历整个数组,将数组中的元素存放到Set中,在存放前先判断该元素是否在Set中,若存在则直接返回该元素
 


public int findReatNumber(int[] nums){
        Set set = new HashSet<Integer>();
        for(int i :nums){
            if(set.contains(i)){
                return i;
            }
            else{
                set.add(i);
            }

    }
        return -1;
    }

题解2:


数组存放的数字范围是在0~n; 所以可以将数组进行排序,将元素归位到和下标对应相等的位置(即一个萝卜一个坑)如果这个萝卜对应的坑位已被占用,说明存在重复。则输出该元素。

public int findReatNumber1(int[] nums){
        int temp;
        for(int i =0;i<nums.length;i++){
            while(i!=nums[i]){
                if(nums[i]==nums[nums[i]]){
                    return nums[i];
                }

                    temp = nums[i];
                    nums[i]=nums[temp];
                    nums[temp]=temp;

            }


        }

        return -1;
    }

题解3:快慢指针

题目可以转化成142. 环形链表 II来做
将数组转化成一个链表,起点为第0个元素值,下一个结点为当前元素作为索引值对应的元素
由于有重复的元素,那么当遍历到重复的元素后必定形成循环。
 

nums[i]23145476
i01234567

此时生成的链表为
2 --> nums[ 2 ] : 1 -->nums[1] :3 --> nums[3] :4 -->nums[ 4 ] : 5 -->nums[5] :4
                                                                                              ^                |
                                                                                              |                 |
                                                                                               ---------------
此时可以使用两个指针 slow 和 fast 分别指向数组第0个元素 nums[0]
环形链表由两部分组成a个结点在环外,b个结点在环内
快指针fast每次走2步 慢指针slow每次走1步,假设slow走了s步后与fast走了f步后相遇, f = 2s
此时fast比slow多走了n个环的步数 即 f = s+nb
两式合并得  s= nb     
那么要确定a的位置 则只需要 slow指针再走 a步,就可以回到环的起点
此时可以将fast重置到 head结点,令fast和slow每次只走1步,当他们再次相遇时即是走了a步
最后返回此时的结点
 

class Solution {
    public int findDuplicate(int[] nums) {
        int slow = nums[0];
        int fast = nums[0];
        while(true){
            slow=nums[slow];
            fast=nums[nums[fast]];
            if(slow==fast){
                break;
            }
        }
        slow = nums[0];
        while(slow!=fast){
            slow=nums[slow];
            fast=nums[fast];
        }
        return slow;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值