剑指Offer——数组中重复的数字

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

分析:

解法一:先排序,再找出重复的数字,可以找出所有重复的数字。

代码如下:

public sealed class SortAndFind
    {
        //快排的单元排序
        private static int SortInit(int[] arr, int low, int high)
        {
            int key = arr[low];
            while (low < high)
            {
                while (arr[high] >= key && high > low)
                    high--;
                arr[low] = arr[high];
                while (arr[low] <= key && low < high)
                    low++;
                arr[high] = arr[low];
            }
            arr[low] = key;
            return low;
        }
        //快排
        private static void QuickSort(int[] arr, int low, int high)
        {
            if (low >= high)
                return;
            int index = SortInit(arr, low, high);
            QuickSort(arr, low, index - 1);
            QuickSort(arr, index + 1, high);
        }
        //找出所有重复的数字
        public static int[] FindRepeatNums(int[] arr)
        {
            List<int> temp = new List<int>();
            QuickSort(arr, 0, arr.Length - 1);
            foreach (int item in arr)
            {
                Console.Write("{0} ", item);
            }
            Console.WriteLine();
            for (int i = 0; i < arr.Length - 1; i++)
            {
                if (arr[i] != arr[i + 1])
                    continue;
                while (arr[i] == arr[i + 1] && i < arr.Length - 2)
                {
                    i++;
                }
                temp.Add(arr[i]);
            }
            int[] result = temp.ToArray();
            return result;
        }
    }

解法二:使用字典存储值和值的数量,可以找出所有重复的数字。

代码如下:

public sealed class DictionaryAndFind
    {
        public static void Find(int[] arr)
        {
            Dictionary<int, int> dictionary = new Dictionary<int, int>();
            for (int i=0;i<arr.Length;i++)
            {
                if (!dictionary.ContainsKey(arr[i]))
                    dictionary.Add(arr[i], 1);
                else
                    dictionary[arr[i]] += 1;
            }
            int[] keys = dictionary.Keys.ToArray();
            for(int j = 0;j<keys.Length;j++)
            {
                if (dictionary[keys[j]] > 1)
                    Console.Write("{0} ", keys[j]);
            }
        }
    }

解法三:仔细分析题目,所有数字都在0~n-1范围内,抓住这个条件,我们可以想假如没有重复的数会怎么样?排好序的话下标与值相等,根据这个来解。假如值等于下标,则往后扫描,否则,先与下标为该值的值比较,若相等,则找到了重复的数,否则,交换两个数。一边排序,一边找重复的数。

代码如下:

public sealed class ChangeAndFind
    {
        public static int FindOneRepeat(int[] arr)
        {
            if (arr == null || arr.Length <= 0)
                return -1;
            for(int i=0;i<arr.Length;i++)
            {
                if (arr[i] < 0 || arr[i] > arr.Length - 1)
                    return -1;
            }
            int one = 0;
            for(int i=0;i<arr.Length;i++)
            {
                while(arr[i]!=i)
                {
                    int temp = arr[i];
                    if (arr[i] == arr[temp])
                    {
                        one = arr[i];
                        return one;
                    }
                    arr[i] = arr[temp];
                    arr[temp] = temp;
                }
            }
            return one;
        }
    }
总结:要仔细分析题目,从而找出最优解。

猜你喜欢

转载自blog.csdn.net/a_clear_chen/article/details/80241040