迅速なアルゴリズム:最大かつサブ

1.説明

その最大戻るを有する(サブアレイが最小要素を含む)NUMSに整数の配列を与えられ、そして連続するサブ配列の最大値を見つけます。

実施例1:入力:[ - 2,3、-1、1、-3]

          出力:3

          説明:連続サブアレイ[3、-1、1]の最大値は3であります

実施例2:入力:[ - 2、1、-3、4、-1、2、1、-5、4]

          出力:6

          説明:連続サブアレイ[4、-1、2、1]及び6の最大

 

2、アルゴリズム

解決策1:暴力ソリューションのサイクル

アイデア:最大の連続サブアレイを見つけるために、2つの変数の最大とレコードの一つで、再び現在と最後のレコードを反復処理し、

時間の複雑さ:O(N ^ 2)

func maxSubArray(_ nums: [Int]) -> Int {
        /*
        暴力循环遍历 O(n^2)
         */
        var nums = nums
        //存最大值
        var maxValue = nums[0]
        var sum = 0
        
        for i in 0..<nums.count {
            sum = 0
            for j in i..<nums.count{
                sum += nums[j]
                if sum > maxValue{
                    maxValue = sum
                }
            }
        }
        return maxValue
    }

対処方法2:動的計画

アイデア:

1)動的プログラミングは、結果は、ANSアレイ、現在の最大連続配列を横断すると合計する第一であります

2)結果バフの和> 0の場合、和、および和プラス予約現在の反復数の場合は

3)合計場合<= 0の場合、結果の合計は全く利得を示さず、放棄する必要があり、合計は、直接現在の反復数に更新されます

4)各和とサイズANSを比較し、ANS最大値に設定され、反復は、完全なリターン結果であります

アイコン:

時間複雑:O(n)は、

func maxSubArray(_ nums: [Int]) -> Int {
       
        var nums = nums
        var ans = nums[0]
        var sum : Int = 0
        for num in nums {
            if sum > 0{
                sum += num
            }else{
                sum = num
            }
            ans = max(ans, sum)
            
        }
        return ans
    }

3、高度な

あなたが解決策のO(N)の複雑さを実装している場合は、分割統治のより洗練された使用を解決しようとします。

解決策1:非再帰的分割統治

アイデア:

1)最大記録処理maxを定義します

2)2つの最終サブシーケンスはlSum、RSUMは、2つの記録から前進し、中間に定義され

3)中間体凝集、及び、最大値をとる:Math.max(MAX、lSum + RSUM)。

func maxSubArray(_ nums: [Int]) -> Int {
        
        var nums = nums
        //过程中最大值
        var maxValue = max(nums[0], nums[nums.count-1])
        //左半部分,最近一次子序和
        var lSum = 0
        //右半部分,最近一次子序和
        var rSum = 0
        
        var i = 0, j = nums.count-1
        while i<=j {
            lSum = lSum>0 ? lSum+nums[i] : nums[i]
            maxValue = max(maxValue, lSum)
            
            if j != i {
                rSum = rSum>0 ? rSum+nums[j] : nums[j]
                maxValue = max(maxValue, rSum)
            }
            
            i += 1
            j -= 1
        }
        
        //汇聚
        //maxValue 左右两边最大的,lSum+rSum 中间聚合
        return max(maxValue, lSum+rSum)
    }

溶液II:再帰的な分割統治

アイデア:再帰によって分割統治が絶えず小型化、三つの問題がある結果、左、右の溶液、及び途中の溶液に溶液(仲介へ位置要求が中間最適解を見つけるの両側から延びている)は、3つのソリューションを与えますサイズを比較することで、最適なソリューションまで。

時間複雑:O(nlogn)

func maxSubArray3(_ nums: [Int]) -> Int {
        return maxSubArrayPart(nums, 0, nums.count-1)
    }
    private func maxSubArrayPart(_ nums : [Int], _ left : Int, _ right : Int)->Int{
        if left == right {
            return nums[left]
        }
        
        let mid = (left+right)/2
        return max(maxSubArrayPart(nums, left, mid), max(maxSubArrayPart(nums, mid+1, right), maxSubArrayAll(nums, left, mid, right)))
    }
    //左右两边合起来求解
    private func maxSubArrayAll(_ nums : [Int], _ left : Int, _ mid : Int, _ right : Int)->Int{
        var leftSum = -2147483648
        var sum = 0
        var i = mid
        while i >= left {
            sum += nums[i]
            if sum > leftSum {
                leftSum = sum
            }
            i -= 1
        }
        sum = 0
        var rightSum = -2147483648
        var j = mid+1
        while j<=right {
            sum += nums[j]
            if sum > rightSum{
                rightSum = sum
            }
            j += 1
        }
        
        return leftSum+rightSum
    }

 

おすすめ

転載: blog.csdn.net/lin1109221208/article/details/92997704