剑指Offer-题3:找出数组中重复的数字

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

主要思路:数组中的数字范围为0~n-1,若没有重复数字,则排序后数字i出现在数组下标为i的位置。但是,因为有重复数字,所以数字和其下标不是一一对应的关系。重排该数组(numbers),从头到尾扫描,当扫描到下标为i时,判断其数值(m)是否等于i。若相等,则继续扫描下一位置。若不相等,则将该数值m与下标为m的数值(numbers[m])比较,若这两个数相等,则找到了第一个重复的数字(该数字在下标为i和m的位置都出现了);若不相等,则交换这两个数的位置,使得数值m 与其下标相等。接下来继续比较交换,直到找到重复的数字。

关键点:找到数值与其索引的关系。

时间复杂度:O(n)

public class DuplicateNumber
{
    public static void main(String[] args)
    {
        int numbers[] = {2, 3, 1, 0, 2, 5, 3};
        int[] duplications = new int[numbers.length];
        boolean isDuplicated = duplicate(numbers, numbers.length, duplications);
        if(isDuplicated)
        {
            System.out.println(duplications[0]);
        }
    }

    private static boolean duplicate(int numbers[], int length, int[] duplication)
    {
        if (numbers == null || length <= 0) return false;
        //判断输入数组是否正确
        for (int i = 0; i < length; i++)
        {
            if (numbers[i] < 0 || numbers[i] > length - 1)
            {
                return false;
            }
        }
        for (int i = 0; i < length; i++)
        {
            //循环直到数值和下标相等
            while (numbers[i] != i)
            {
                int currentNumber = numbers[i];
                //该数字出现两次
                if (currentNumber == numbers[currentNumber])
                {
                    duplication[0] = currentNumber;
                    return true;
                }
                //交换
                int temp = numbers[currentNumber];
                numbers[currentNumber] = currentNumber;
                numbers[i] = temp;
            }
        }
        return false;
    }
}

猜你喜欢

转载自blog.csdn.net/m0_37862405/article/details/80032369
今日推荐