C#算法——向一个集合中随机插入100个不重复的数值

请使用C#将一个长度为100的 int 数组,插入1-100的随机数,不能重复,要求遍历次数最少。

逐句思考:

首先,想要产生100个随机数

可以使用 for 循环

List<int> list = new List<int>();
for (int i = 0; i < 100; i++)
{
	int num = r.Next(1, 101);
	list.Add(num);
}

这样,数组中就有了100个随机数。

但是,这100个随机数是包含重复值的,所以,方法不适用。

其次,不能重复。

那就拒绝已添加的数值再次加入。

设定一个判断

if (!list.Contains(num))
{
	list.Add(num);
}

这样,可以确保数组内的数值都是唯一的,但是数组元素个数将不足100。

最后,遍历次数最少

没有最好,只有更好——算法优化。

回归正题:

方法一:

var r = new Random();
List<int> list = new List<int>();
int count = 0;
while (list.Count < 100)
{
	int num = r.Next(1, 101);
	if (!list.Contains(num))
	{
		list.Add(num);
	}
	count++;
}
foreach (var i in list)
{
	Console.Write(i + "\t");
}
Console.WriteLine("一共遍历了{0}次", count);

方法二:

使用 HashSet

HashSet存放元素过程:
将一个元素存入HashSet中时,HashSet会先调用对象的hashCode方法,以此确定对象的存储位置,之后HashSet会查询对应的hashCode位置是否已经存储对象
{
  如果存储了,则会调用equals方法判断两个对象是否相同:
   {
    如果相同:
    {
      则不存储。
    }
    如果不同:
    {
      则在相同的hashCode位置使用链表的形式存储进去,但会影响HashSet性能。
    }
  }
  如果没有存储:
  {
    则直接存储进去。
  }
}

与方法一差别不大,只是少了一个 if 判断。

var r = new Random();
HashSet<int> h = new HashSet<int>();
int count = 0;
while (h.Count < 100)
{
	h.Add(r.Next(1, 101));
	count++;
}
foreach (var i in h)
{
	Console.Write(i + "\t");
}
Console.WriteLine("一共遍历了{0}次", count);

方法三:

List<int> list1 = new List<int>(), list2 = new List<int>();
var count = 0;
for (int i = 1; i < 101; i++)
{
	list1.Add(i);
	count++;
}
var r = new Random();
while (list2.Count < 100)
{
	var index = r.Next(0, list1.Count);
	list2.Add(list1[index]);
	list1.RemoveAt(index);
	count++;
}
foreach (var i in list2)
{
	Console.Write(i + "\t");
}
Console.WriteLine("一共遍历了{0}次", count);

此方案一共遍历200次,初始化遍历100次,重新赋值再遍历100次,并且数字是随机不重复的。

每遍历一次,list1就会删除一个元素,即使产生的随机数据相同,但每次对于list1的索引对应的值是不同的,能保证数字唯一性。

附:完整代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace project_Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Test.Method1();
            Test.Method2();
            Test.Method3();
        }
    }

    class Test
    {
        public static void Method1()
        {
            var r = new Random();
            List<int> list = new List<int>();
            int count = 0;
            while (list.Count < 100)
            {
                int num = r.Next(1, 101);
                if (!list.Contains(num))
                {
                    list.Add(num);
                }
                count++;
            }
            foreach (var i in list)
            {
                Console.Write(i + "\t");
            }
            Console.WriteLine("一共遍历了{0}次", count);
        }

        public static void Method2()
        {
            var r = new Random();
            HashSet<int> h = new HashSet<int>();
            int count = 0;
            while (h.Count < 100)
            {
                h.Add(r.Next(1, 101));
                count++;
            }
            foreach (var i in h)
            {
                Console.Write(i + "\t");
            }
            Console.WriteLine("一共遍历了{0}次", count);
        }

        public static void Method3()
        {
            List<int> list1 = new List<int>(), list2 = new List<int>();
            var count = 0;
            for (int i = 1; i < 101; i++)
            {
                list1.Add(i);
                count++;
            }
            var r = new Random();
            while (list2.Count < 100)
            {
                var index = r.Next(0, list1.Count);
                list2.Add(list1[index]);
                list1.RemoveAt(index);
                count++;
            }
            foreach (var i in list2)
            {
                Console.Write(i + "\t");
            }
            Console.WriteLine("一共遍历了{0}次", count);
        }
    }
}

附:原文地址

over.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值