【问题标题】:How to Implement MaxSubArray in C#? [closed]如何在 C# 中实现 MaxSubArray? [关闭]
【发布时间】:2013-03-15 07:24:56
【问题描述】:

我正在尝试用 C# 开发 Max Sub Array Problem

我的代码是

try
        {
            int[] Values = { 9, 1, 4, 15, -5, -41, -8, 78, 145, 14 };//Will be executed once '1'


            int StartIndex = 0;//Will be executed once '1'
            double Sum = 0;//Will be executed once '1'
            double Temp = 0;//Will be executed once '1'
            double Max = 0;//Will be executed once '1'

            do
            {

                for (int i = 0; i < Values.Length; i++)//1+(N+1)+N
                {
                    Sum = Values[StartIndex];

                    if (StartIndex < i)
                    {
                        for (int j = StartIndex+1; j <= i; j++)
                        {
                            Sum += Values[j];
                        }

                        if (Sum > Temp)
                        {
                            Max = Sum;
                            Temp = Sum;
                        }
                    }
                }
                StartIndex++;
            } while (StartIndex<Values.Length);


            MessageBox.Show("The Max Value is " + Max);



        }
        catch { }

我想知道这是否是解决此算法的最佳方法,因为我正在尝试最小化时间复杂度

感谢大家的宝贵时间

【问题讨论】:

  • 最好在代码审查上发布您的问题 - codereview.stackexchange.com
  • 我没有在你的代码中看到任何高级操作。你有什么理由把它放在 try 块中吗?

标签: c# algorithm


【解决方案1】:

这里有一个 O(N) 算法:http://en.wikipedia.org/wiki/Maximum_subarray_problem

它实际上并没有给你子数组,只是子数组的最大值。

注意输入数组必须包含至少一个正数(非零)的重要限制。

我已经修改它以返回范围以及最大值:

using System;

namespace Demo
{
    public static class Program
    {
        public static void Main(string[] args)
        {
            //int[] numbers = new[] { -2, 1, -3, 4, -1, 2, 1, -5, 4 };
            //int[] numbers = new[] { 1, 1, 1, 1, 1, 1, 1, 1 };

            int[] numbers = new[] {9, 1, 4, 15, -5, -41, -8, 78, 145, 14};

            var result = FindMaximumSubarray(numbers);

            Console.WriteLine("Range = {0}..{1}, Value = {2}", result.StartIndex, result.EndIndex, result.Value);
        }

        public static MaximumSubarray FindMaximumSubarray(int[] numbers)
        {
            int maxSoFar = numbers[0];
            int maxEndingHere = numbers[0];
            int begin = 0;
            int startIndex = 0;
            int endIndex = 0;

            for (int i = 1; i < numbers.Length; ++i)
            {
                if (maxEndingHere < 0)
                {
                    maxEndingHere = numbers[i];
                    begin = i;
                }
                else
                {
                    maxEndingHere += numbers[i];
                }

                if (maxEndingHere > maxSoFar)
                {
                    startIndex = begin;
                    endIndex = i;
                    maxSoFar = maxEndingHere;
                }
            }

            return new MaximumSubarray
            {
                StartIndex = startIndex,
                EndIndex = endIndex,
                Value = maxSoFar
            };
        }

        public struct MaximumSubarray
        {
            public int StartIndex;
            public int EndIndex;
            public int Value;
        }
    }
}

【讨论】:

    【解决方案2】:

    您的代码的时间复杂度为O(n^3),但您可以使用两个renovations 对其进行改进,并将其更改为O(N^2)。但有更好的algorithmthis 是由动态规划设计的。

    this 解决方案在矩阵数组中求解。 注意:最大默认值应设置为无限负数。

    这是来自维基的代码:

    在整个数组由负数组成的情况下不允许返回零长度子数组的问题的变体可以使用以下代码解决,此处用 C++ 编程语言表示。

    int sequence(std::vector<int>& numbers)
    {
            // Initialize variables here
            int max_so_far  = numbers[0], max_ending_here = numbers[0];
            size_t begin = 0;
            size_t begin_temp = 0;
            size_t end = 0;
            // Find sequence by looping through
            for(size_t i = 1; i < numbers.size(); i++)
            {
                    // calculate max_ending_here
                    if(max_ending_here < 0)
                    {
                            max_ending_here = numbers[i];
                            begin_temp = i;
                    }
                    else
                    {
                            max_ending_here += numbers[i];
                    }
                    // calculate max_so_far
                    if(max_ending_here > max_so_far )
                    {
                            max_so_far  = max_ending_here;
                            begin = begin_temp;
                            end = i;
                    }
            }
            return max_so_far ;
    }
    

    【讨论】:

    • 感谢@MatthewWatson。我将此链接附加到算法字中
    • 酷 - 我删除了我现在多余的评论。 :) 顺便说一句,您是否注意到 beginend 的值从未使用过?并不是维基百科上最好的代码!
    • 开始 = begin_temp;结束=我; ???
    【解决方案3】:

    Inroduction to Algorithms: CLRS,第 4 章分而治之 4.1 最大子数组问题中描述了具有 O(N*logN) 复杂度的分治法实现。 C# 端口from

     class Program {
        static void Main(string[] args) {
            int[] values = { 9, 1, 4, 15, -5, -41, -8, 78, 145, 14 };
            Console.WriteLine(FindMaxSubarray(values, 0, values.Length - 1));
        }
    
        public struct MaxSubArray {
            public int Low;
            public int High;
            public int Sum;
    
            public override string ToString() {
                return String.Format("From: {0} To: {1} Sum: {2}", Low, High, Sum);
            }
        }
    
        private static MaxSubArray FindMaxSubarray(int[] a, int low, int high) {
            var res = new MaxSubArray {
                Low = low,
                High = high,
                Sum = a[low]
            };
            if (low == high) return res;
    
            var mid = (low + high) / 2;
            var leftSubarray = FindMaxSubarray(a, low, mid);
            var rightSubarray = FindMaxSubarray(a, mid + 1, high);
            var crossingSubarray = FindMaxCrossingSubarray(a, low, mid, high);
    
            if (leftSubarray.Sum >= rightSubarray.Sum &&
                leftSubarray.Sum >= crossingSubarray.Sum)
                return leftSubarray;
            if (rightSubarray.Sum >= leftSubarray.Sum &&
                     rightSubarray.Sum >= crossingSubarray.Sum)
                return rightSubarray;
            return crossingSubarray;
        }
    
        private static MaxSubArray FindMaxCrossingSubarray(int[] a, int low, int mid, int high) {
            var maxLeft = 0;
            var maxRight = 0;
    
            var leftSubarraySum = Int32.MinValue;
            var rightSubarraySum = Int32.MinValue;
    
            var sum = 0;
            for (var i = mid; i >= low; i--) {
                sum += a[i];
                if (sum <= leftSubarraySum) continue;
                leftSubarraySum = sum;
                maxLeft = i;
            }
    
            sum = 0;
            for (var j = mid + 1; j <= high; j++) {
                sum += a[j];
                if (sum <= rightSubarraySum) continue;
                rightSubarraySum = sum;
                maxRight = j;
            }
    
            return new MaxSubArray {
                Low = maxLeft,
                High = maxRight,
                Sum = leftSubarraySum + rightSubarraySum
            };
    
        }
    }
    

    【讨论】:

      【解决方案4】:

      试试这个

      static void Main()
          {
              try
              {
                  int[] Values = { 9, 1, 4, 15, -5, -41, -8, 78, 145, 14 };//Will be executed once '1'
      
                  int max_ending_here = 0;
                  int max_so_far = 0;
      
                  foreach(int x in Values)
                  {
                      max_ending_here = Math.Max(0, max_ending_here + x);
                      max_so_far = Math.Max(max_so_far, max_ending_here);
                  }
      
                  Console.WriteLine("The Max Value is " + max_so_far);
                  Console.ReadKey();
              }
              catch { }
          }
      

      Reference Source

      【讨论】:

        猜你喜欢
        • 2023-03-26
        • 1970-01-01
        • 2017-06-13
        • 1970-01-01
        • 2012-08-09
        • 1970-01-01
        • 1970-01-01
        • 2019-04-16
        • 2010-10-24
        相关资源
        最近更新 更多