【问题标题】:find the min value in int array with C#用 C# 找到 int 数组中的最小值
【发布时间】:2010-11-07 20:39:32
【问题描述】:

如何使用 c# 找到 int 数组中的最小值

【问题讨论】:

    标签: c#


    【解决方案1】:

    使用 LINQ:

    int min = theArray.Min();
    

    请注意,如果没有 any 元素,这将出错;首先检查.Length(或者,投影到int?,但这会增加开销)。

    如果您没有可用的 LINQ,那么可能:

    public static int Min(int[] arr) {
        switch (arr.Length) {
            case 0: throw new InvalidOperationException();
            case 1: return arr[0];
            case 2: return Math.Min(arr[0], arr[1]);
            default:
                int min = arr[0];
                for (int i = 1; i < arr.Length; i++) {
                    if (arr[i] < min) min = arr[i];
                }
                return min;
        }
    }
    

    【讨论】:

    • 这是什么意思? case 2: return Math.Min(arr[0], arr[1]);默认你在做什么?
    • 还有什么意思? case 1: return arr[0];?
    • @SaeedAlg - 我正在检查数组的长度;如果是 1 项,则 min 显然是第一个(唯一)项;如果有 2 个,则将其视为另一种特殊情况因为我们可以方便地这样做 - 否则我们将遍历数组并找到最小值
    • 你不能对它们做任何事情,你的默认值意味着你对12的数组大小执行此操作,在case中无需执行此操作,您只需要一个简单的 if声明,但如果你说这样做是为了可读性,那是可以接受的。
    • @Doggett - 很好,随心所欲。老实说,过度分析了吗?编写的代码可以正常工作并通过我能想到的任何(理智的)测试。随意发布更简单的版本;我会很高兴地支持它!但也请注意我回答的第一部分....Min()...
    【解决方案2】:

    我写了下面的内容来比较@Marc Gravell 所说的话,我告诉的方式在我的 PC 中要快一点,而 linq 是最慢的方式,此外,如果您更改函数的位置(在代码中),您将使用if 的版本总是会获得更好的性能

        static void Main(string[] args)
        {
            Dictionary<string, List<long>> dic = new Dictionary<string, List<long>>();
    
            dic["First"] = new List<long>();
            dic["Second"] = new List<long>();
            dic["Third"] = new List<long>();
    
    
            for (int i = 0; i < 500; i++)
            {
                int[] array = GetRandomArray();
                Stopwatch stopWacth = new Stopwatch();
                stopWacth.Restart();
                int n1 = FindMin(array);
                stopWacth.Stop();
                long firstTicks = stopWacth.ElapsedTicks;
                dic["First"].Add(firstTicks);
    
                stopWacth.Restart();
                int n2 = AnotherFindMin(array);
                stopWacth.Stop();
                long secondTick = stopWacth.ElapsedTicks;
                dic["Second"].Add(secondTick);
    
                stopWacth.Restart();
                int n3 = array.Min();
                stopWacth.Stop();
                long thirdTick = stopWacth.ElapsedTicks;
                dic["Third"].Add(thirdTick);
    
                Console.WriteLine("first tick : {0}, second tick {1}, third tick {2} ", firstTicks, secondTick, thirdTick);
            }
    
            Console.WriteLine("first tick : {0}, second tick {1}, third tick {2} ", dic["First"].Average(), dic["Second"].Average(), dic["Third"].Average());
    
            Console.ReadLine();
        }
    
    
        public static int[] GetRandomArray()
        {
            int[] retVal = new int[1000000];
            Random r = new Random();
            for (int i = 0; i < 1000000; i++)
            {
                retVal[i] = r.Next(1000000000);
            }
            return retVal;
        }
    
        public static int FindMin(int[] arr)
        {
            switch (arr.Length)
            {
                case 0: throw new InvalidOperationException();
                case 1: return arr[0];
                case 2: return Math.Min(arr[0], arr[1]);
                default:
                    int min = arr[0];
                    for (int i = 1; i < arr.Length; i++)
                    {
                        if (arr[i] < min) min = arr[i];
                    }
                    return min;
            }
        }
    
        public static int AnotherFindMin(int[] arr)
        {
            if (arr.Length > 0)
            {
                int min = arr[0];
                for (int i = 1; i < arr.Length; i++)
                {
                    if (arr[i] < min) min = arr[i];
                }
                return min;
            }
            else
            {
                throw new InvalidOperationException();
            }
        }
    }
    // revised test by Marc (see comments discussion)
    static class Test {
        static void Main(string[] args)
        {
            Dictionary<string, List<long>> dic = new Dictionary<string, List<long>>();
    
            dic["First"] = new List<long>();
            dic["Second"] = new List<long>();
            dic["Third"] = new List<long>();
    
            const int OUTER_LOOP = 500, INNER_LOOP = 500000;
            for (int arrSize = 1; arrSize <= 3; arrSize++)
            {
                for (int i = 0; i < OUTER_LOOP; i++)
                {
                    int[] array = GetRandomArray(arrSize);
                    Stopwatch stopWacth = Stopwatch.StartNew();
                    for (int j = 0; j < INNER_LOOP; j++)
                    {
                        int n1 = FindMin(array);
                    }
                    stopWacth.Stop();
                    long firstTicks = stopWacth.ElapsedTicks;
                    dic["First"].Add(firstTicks);
    
                    stopWacth = Stopwatch.StartNew();
                    for (int j = 0; j < INNER_LOOP; j++)
                    {
                        int n2 = AnotherFindMin(array);
                    }
                    stopWacth.Stop();
                    long secondTick = stopWacth.ElapsedTicks;
                    dic["Second"].Add(secondTick);
    
                    stopWacth = Stopwatch.StartNew();
                    for (int j = 0; j < INNER_LOOP; j++)
                    {
                        int n3 = array.Min();
                    }
                    stopWacth.Stop();
                    long thirdTick = stopWacth.ElapsedTicks;
                    dic["Third"].Add(thirdTick);
    
                    //Console.WriteLine("{3}: switch : {0}, 0-check {1}, Enumerable.Min {2} ", firstTicks, secondTick, thirdTick, arrSize);
                }
    
                Console.WriteLine("{3}: switch : {0}, 0-check {1}, Enumerable.Min {2} ", dic["First"].Average(), dic["Second"].Average(), dic["Third"].Average(), arrSize);
            }
            Console.WriteLine("Done");
            Console.ReadLine();
        }
    
    
        public static int[] GetRandomArray(int size)
        {
            int[] retVal = new int[size];
            Random r = new Random();
            for (int i = 0; i < retVal.Length; i++)
            {
                retVal[i] = r.Next(1000000000);
            }
            return retVal;
        }
    
        public static int FindMin(int[] arr)
        {
            switch (arr.Length)
            {
                case 0: throw new InvalidOperationException();
                case 1: return arr[0];
                case 2: return arr[0] < arr[1] ? arr[0] : arr[1];
                default:
                    int min = arr[0];
                    for (int i = 1; i < arr.Length; i++)
                    {
                        if (arr[i] < min) min = arr[i];
                    }
                    return min;
            }
        }
    
        public static int AnotherFindMin(int[] arr)
        {
            if (arr.Length > 0)
            {
                int min = arr[0];
                for (int i = 1; i < arr.Length; i++)
                {
                    if (arr[i] < min) min = arr[i];
                }
                return min;
            }
            else
            {
                throw new InvalidOperationException();
            }
        }
    }
    

    【讨论】:

    • 一个Stopwatch 在一次迭代中不会给出有意义的答案;此外,此测试仅考虑default 情况(公平地说,这是最有可能的)。而且该数组如此非常大,以至于任何测试几乎没有显示来自这种逻辑选择的任何数字...
    • @Marc Gravell,我写的是平均水平
    • (编辑:我的错误,这是 4.0 方法)另外 - Restart - 那是你的扩展方法吗?我正在(本地)替换 Stopwatch.StartNew()
    • @Marc Gravell,我认为这并非毫无意义,但如果你这么认为,你有什么想法来比较它们?我得到了数组的大小,所以秒表应该没有意义,你的建议是什么?
    • 不,我在 .Net 4 中使用 using System.Diagnostics;,重启不适合我,@Marc Gravell,你应该注意程序集跳转,这对我的方法来说更长
    猜你喜欢
    • 2015-11-29
    • 2015-02-03
    • 2022-08-10
    • 1970-01-01
    • 2012-09-27
    • 2013-04-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多