3 配列内の繰り返し番号 (ソードフィンガー)

找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。
数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。
请找出数组中任意一个重复的数字。
示例 1:
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3 
限制:
2 <= n <= 100000
namespace ConsoleApp2;
public class 数组中重复的数字
{
   //思路1:拿到一个数,就把他存放到字典里,值当做key,value当位置,然后每一次放入字典前,看看这个数是不是已经存在了,存在就直接返回
   //时间是O(n),空间是O(n)
   public static int FindRepeatNumber(int[] nums)
   {
       Dictionary<int, int> dic = new Dictionary<int, int>();
       for (int i = 0; i < nums.Length; i++)
       {
           if (dic.ContainsKey(nums[i]))
           {
               return nums[i];
           }
           else
           {
               dic.Add(nums[i],i);
           }
       }
       return 0;
   }
   //思路2,考虑到题目是n 的数组 nums 里的所有数字都在 0~n-1 的范围内,这么可以确定,数字可以重复,那么一个索引可以对应多个值
   // 想象:打地主,很多农民,很多钱袋(上面印着属于谁),找出谁家有两个钱袋,这些钱袋现在均匀的分在农民手中
   //例如[2, 3, 1, 0, 2, 5, 3]
   // 怎么快速的找出谁的钱袋多,农民0号,拿出他身上分的钱袋,一看是属于2号的,立马找2号去换,
   // 看看2号手中是不是自己的钱袋,如果2号手中已经有自己的钱袋了,那么2号钱袋一定是重复的,这个叼毛就是地主
   // 如果2号手中不是自己的钱袋,那么当场进行交换,这样能去确保2号已经有自己的钱袋了,自己拿到了1号钱袋
   
   // 然后0号农民拿着1号钱袋找1号农民交换,操作如上面操作,直到,0号农民拿到了自己的钱袋,那么就进行索引加1,
   
   // 然后1号农民去拿着自己的钱袋去上述操作
   // 时间复杂度是0(n),空间是O(1)
   public static int FindRepeatNumber2(int[] nums)
   {
       for (int i = 0; i < nums.Length; )
       {
           //农民先看看手里的钱袋是不是自己的,是的话直接不管了,下一个农民继续
           if (nums[i] == i)
           {
               i++;
           }
           //不是自己的钱袋
           else
           {
               //如果自己手里钱袋nums[i]的主人nums[i]手里已经有属于自己的钱袋了nums[nums[i],那么他一定是超过一个钱袋的,是地主
               if (nums[nums[i]] == nums[i])
               {
                   return nums[i];
               }
               //对方手里钱袋不是他自己的,那么与他进行交换,确保对方手里钱袋是自己的
               else
               {
                   var temp_data = nums[i];
                   nums[i] = nums[temp_data];
                   nums[temp_data] = temp_data;
                   // 下面是错误示例,nums[i]会在第二行被改变,导致第三行有问题,所以一定要用temp_data
                   // var temp_data = nums[i];
                   // nums[i] = nums[nums[i]];
                   // nums[nums[i]] = temp_data;
               }
           } 
           //然后拿着交换来的钱袋继续去找,直到找到属于自己的钱袋(i++),或者找到对方多了一个钱袋(返回结果)。这两个结果必定会出现其中之一
       }
       return 0;
   }  
   static void Main(string[] args)
   {
       int num = FindRepeatNumber2(new int[] {1,2,1,1});
       Console.WriteLine(num);
   }
}

おすすめ

転載: blog.csdn.net/qq_32175379/article/details/124424944