0

我正在尝试在 C#中开发最大子数组问题

我的代码是

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 { }

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

谢谢大家的时间

4

4 回答 4

1

您的代码的时间复杂度是O(n^3),但您可以通过两次翻新来改进它并将其更改为O(N^2). 但是有一个更好的算法或者这个由动态规划设计的。

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

这是来自维基的代码:

在整个数组由负数组成的情况下,不允许返回零长度子数组的问题的变体可以使用以下代码解决,此处用 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 ;
}
于 2013-03-15T08:25:46.983 回答
1

具有 O(N*logN) 复杂度的分而治之的实现在算法简介:CLRS,第 4 章分而治之 4.1 最大子数组问题中进行了描述。C# 端口来自.

 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
        };

    }
}
于 2013-03-15T08:13:14.997 回答
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;
        }
    }
}
于 2013-03-15T08:54:55.457 回答
0

尝试这个

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 { }
    }

参考来源

于 2013-03-15T08:25:44.790 回答