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
}