2、寻找重复数字

寻找重复数字

大致有两种不同版本:

1

给定一个包含 n + 1 个整数的数组 nums ,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。

假设 nums 只有 一个重复的整数 ,找出 这个重复的数 。

2

找出数组中重复的数字。


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

示例 1:

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

限制:

2 <= n <= 100000

总结

对于1 与 2 通用解法为
1、采用hashSet排重 时间复杂度On 空间复杂度On
2、采用排序算法 时间复杂度Onlogn 空间复杂度O1

对于版本1 由于特殊的数字设定 此处有两种解决方法:

    //将数字想象成一个个链表节点:将问题转换为:寻找有环列表的起始节点
    public int findDuplicate(int[] nums) {
        //[0],[1,2,3,1],[1,1,1,1],[]
        int slow = nums[0];
        int fast = nums[nums[0]];
        while (slow != fast){
            slow = nums[slow];
            fast = nums[nums[fast]];
        }
        int find = 0;
        while (find != slow){
            find = nums[find];
            slow = nums[slow];
        }
        return find;
    }

    //halfrost巧解 只适用于1 - n的情况
    public int findDuplicate(int[] nums) {
        for (int i = 0; i < nums.length;i++){
            int var = Math.abs(nums[i]);
            if (nums[var - 1] < 0 ) return var;
            nums[var - 1] *= -1;
        }
        return -1;
    }

对于版本2 此处可使用版本1-1 变体 将数字同同步+1 转换 也可使用如下需要修改数组的方法

    public int findRepeatNumber(int[] nums) {
        //[0],[0,1,2,0],[1,1,1,1],[]
        for (int i = 0; i < nums.length;){
            if (nums[i] == i){
                i++;
                continue;
            }
            else if (nums[i] == nums[nums[i]]){
                return nums[i];
            }else{
                exchange(nums, i, nums[i]);
            }
        }
        return -1;
    }

    public void exchange(int[] nums, int posa, int posb){
        int temp = nums[posa];
        nums[posa] = nums[posb];
        nums[posb] = temp;
    }

总结

1、首先确定要求 遵循如下几个原则
1、能否对入参进行修改?
2、有无时间、空间复杂度要求?
3、需要考虑的特殊情况, 边界条件有哪些?
2、完成1后 先编写测试用例 尽量能覆盖以上几种情况
编写完成代码后需要对已编写的测试用例逐一进行口算测试

posted @ 2021-04-17 15:59  backTraced  阅读(580)  评论(1编辑  收藏  举报