【JAVA学习——数组应用(LeetCode 剑指offer03)】

题目内容:

找出数组中重复的数字。

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

示例 1:

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

限制:

2 <= n <= 100000

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解法1:

思路:使用集合set来实现(Python也有此方法)。通过集合可以实现无重复
数据。基于集合的特性,可以事先创建一个空集合,然后依次遍历数组元素,对每一个遍历的元素进行判断:若集合中无此元素,则将其加入集合中;反之,则此元素为数组的重复数据。
复杂度分析:
时间复杂度:O(n)
空间复杂度:O(n)
具体代码,如下:

//解法一:用集合set解决
    public static int  findRepeatNumber1(int[] nums){
        Set<Integer> set = new HashSet<>();//集合
        for (int value: nums){//--iter 快捷键
            if (set.contains(value)){//set方法,包含
                return value;
            }else{
                set.add(value);
            }

        }
        return -1;
    }

**相关知识:**此方法使用了JAVA中的Set类。

import java.util.HashSet;  import java.util.Set;

Set的常用方法有:
set.contains(value) —— return boolean;
set.add(value) —— return boolean;
set.toString() —— return String;
set.clear() —— void;
set.isEmpty() —— return boolean;
set.size() —— return int;

解法2:

思路:排序+遍历查找。通过随原数组遍历排序,此时,若存在重复数据,他们的位置必定是相邻的。因此,排好序后,只需要判断num[j]是否等于num[j-1];(0<j<n)。
复杂度分析:
时间复杂度:O(n)
空间复杂度:O(1)
代码如下:

 //解法二: 排序思路
    public static int findRepeatNumber2(int[] nums){
        Arrays.sort(nums);//--------使用工具类Array操作数组,sort--void
        for (int i=1;i<nums.length;i++){//--itar快捷键
            if (nums[i-1]==nums[i]){
                return nums[i];
            }
        }

        return -1;
    }

相关知识:此方法使用了JAVA中的Arrays类。

import java.util.Arrays;

Arrays类中的常用方法:
Arrays.sort(数组) —— void;
Arrays.equal(数组1,数组2) —— return boolean;
Arrays.toString(数组) —— return String;

解法3:

思路:临时数组。因为数组内的所有元素其值均不大于n(数组长度)。所以,可以创建一个长度为n的空数组temp(java创建空数组(int类型),实际数组的所有值为0)。然后,依次遍历原数组,将遍历原数组的值放在与temp数组索引值相等的位置。即,temp[num[i]]=num[i].当某次遍历原数组的值所对应的temp数组索引处的值不等于0时,即该值就是我们要找的重复值。
复杂度分析:
时间复杂度:O(n);
空间复杂度:O(n)。
具体代码如下:

//解法三:临时数组
    public static int findRepeatNumber3(int[] nums){
        int[] temp = new int[nums.length];
        for (int i=0;i<nums.length;i++){
            if (temp[nums[i]]!=0){
                return nums[i];
            }
            temp[nums[i]]=1;
        }
        return -1;

    }

解法四:

思路:在解法三的基础上提出解法四,解法三是创建一个临时数组,时间复杂度为O(n)。考虑是否不用创建临时数组,在原数组上进行修改。即,数组元素需要满足于索引值和数组值相等,记此要求为要求一。操作如下:遍历原数组,遍历元素的值若不满足要求一,则将此元素值和与元素值相等的索引值处的数组值进行交换;交换后仍需在原来元素值的位置处继续判断这个交换过来的值是否满足要求一(所以此处有个循环后退操作,即i–;)。若不满足,继续进行重复交换值操作。反之,满足要求一,则遍历下一个数组位置(i++;)。在执行此操作的过程中,若遍历元素值与该值相等索引值所对应的值相等,即此元素值为重复值。
复杂度分析:
时间复杂度:O(n)
空间复杂度:O(1)

具体代码:

public static int findRepeatNumber4(int[] nums){
        System.out.println(Arrays.toString(nums));

        for (int i=0;i<nums.length;i++) {
            if (nums[i] != i) {
                if (nums[nums[i]] != nums[i]) {
                    int tmp = nums[nums[i]];
                    nums[nums[i]] = nums[i];
                    nums[i] = tmp;
                } else {
                    return nums[nums[i]];
                }
            }
            i--;//交换后还需要从当前位置开始判断,所以要i--,抵消i++
            //System.out.println(Arrays.toString(nums));

        }

        return -1;
    }

题目来源于LeetCode,个人学习分享,若有错误,希望大家多多帮忙指出。题目链接:https://leetcode.cn/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值