码迷,mamicode.com
首页 > 编程语言 > 详细

经典算法题-基础-找出重复的数字

时间:2019-09-29 09:36:23      阅读:96      评论:0      收藏:0      [点我收藏+]

标签:out   没有   false   题目   ||   位置   解决   java   static   

问题描述

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

要求
时间限制:1秒
空间限制:32768K

方法原型

public boolean duplicate(int numbers[],int length,int [] duplication)

返回值说明:如果输入有效,并且数组中有重复出现的数字返回true,否则返回false

样例

如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。

这个问题有一个特别的地方,那就是只需要找出任意一个重复的数字,而不是找出所有重复的数字。这使得我们可以在后续的分析中进行算法的优化。
我们接下来介绍的三种解法,可以体现这个特点。

第一种解法:排序+遍历

我们先分析没有重复的情况,如果n个数字没有重复(范围在0到n-1之间)的话,并且有序放入n个大小的数组,那么每个元素的下标与数字值应相等
反之,如果有重复,存在某个元素的下标与数字值不想等。
我们第一种解法就可采取“排序+遍历”的思路:

  • 先对数组进行排序
  • 遍历排序后的数组,找到下标与数字值不一样的元素,即找到重复数字

技术图片

若第一步排序采用快排,这种解法的时间复杂度为\(O(nLog(n))\),空间复杂度为\(O(1)\)

第二种解法:空间换时间

我们还可以采用空间换时间的方法解决这个问题,具体而言,就是另外准备一个容器,该容器中存放每个数字出现次数(计数器),一边遍历待检测数组,一边设置计数器容器,并找寻重复的数字。
具体步骤如下:

  • 计数器容器全部初始化
  • 依次遍历待检测数组,并将对应的计数器设置数值
  • 如果检测到计数器是数值已经修改过,则找到重复数字
    技术图片

这种解法的时间复杂度为\(O(n)\);因为需要额外的计数器容器,空间复杂度也为\(O(n)\)

第三种解法:优化空间

第三种算法,其实是基于第一种算法中提到的,“如果n个数字(0到n-1范围内)没有重复,且有序上升,则放入n个大小的数组中,那么每个元素的下标与数字值应相等”。
只不过我们不再采用一般的排序算法将无序的待检测数组变得有序,而是采用“遍历+置换”的方法,具体过程如下:

  • 遍历待检测数组
  • 如果当前元素的下标与元素数字值一样,则继续遍历下一项
  • 如果当前元素的下标与元素数字值不一样,则将数字值作为【另一个数字】的下标找到另外的一个数字,并与当前元素数字进行交换

如此不断置换,可以得到有序数组,以下是演示:
技术图片

既然数组中如果全部没有重复数字,我们可以利用以上方法得到有序数组。那么如果数组中有重复数字呢?那么我们在利用以上方法排序过程中,必然会遇到下标不同,但是数字相同的两元素,那样,就找到了重复数字。
动图演示如下:
技术图片
这种解法,时间复杂度为\(O(n)\),空间复杂度为\(O(1)\),是目前最优的解法。
相关代码展示如下:

package com.shellmad;

public class Solution {

    public static void main(String[] args) {
        int[] numbers = {2, 3, 1, 0, 4, 5, 6};
        int[] duplication = new int[1];
        Solution solution = new Solution();
        if (solution.duplicate(numbers, numbers.length, duplication)) {
            System.out.println(duplication[0]);
        } else {
            System.out.println("没有重复元素");
        }

    }

    public boolean duplicate(int numbers[], int length, int[] duplication) {

        // 检查输入
        if (numbers == null || numbers.length == 0) {
            return false;
        }

        for (int index = 0; index < numbers.length; index++) {
            if (numbers[index] < 0 || numbers[index] >= numbers.length) {
                return false;
            }
        }

        for (int index = 0; index < numbers.length; index++) {
            while (numbers[index] != index) {
                if (numbers[index] == numbers[numbers[index]]) {
                    duplication[0] = numbers[index];
                    return true;
                }

                // 交换元素的位置
                int temp = numbers[index];
                numbers[index] = numbers[temp];
                numbers[temp] = temp;
            }
        }
        return false;
    }
}

经典算法题-基础-找出重复的数字

标签:out   没有   false   题目   ||   位置   解决   java   static   

原文地址:https://www.cnblogs.com/shellmad/p/11605533.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!