首先暴力搜尋:
public* @description nums 的大小決定問題規模,按 nums 大小分割問題final
int maxsubarray1(int
nums)
max =math.max(max, temp);}}
return
max;
}
* 因為求任意子陣列,按區間對 nums 進行分段
* g(start,end) 表示 start 開頭, end 結尾的陣列的和
* 嘗試列出狀態轉移方程:
* g(start,end)=g(start,end-1)+nums[end]
* start==end 時,以 nums[start] 回歸
* 如果建立快取,則快取空間類似線段樹,儲存了各個區間的區間和
* 但基於陣列長度最大可能達到 10 的 5 次方,因此陣列快取不可取,可用 雜湊表 進行快取
int max =integer.min_value;* @description 上述解法還是超時了,我們嘗試重新定義子問題,使子問題包含更多的運算邏輯,從而更加高效的查詢快取public
final
int maxsubarray2(int
nums)
return
max;
}public
int maxsubarray(int nums, int start, int end, mapcache)
string key = string.valueof(start) + "," +string.valueof(end);
if(cache.keyset().contains(key))
int re = maxsubarray(nums, start, end - 1, cache) +nums[end];
cache.put(key, re);
max =math.max(re, max);
return
re; }
* 子問題包含的運算邏輯越多,則快取命中時,避免的運算也越多
* 子問題的定義需要我們可以找出子問題與上層問題間的狀態轉移關係。
* 我們可以從狀態轉移關係判斷,該狀態轉移路徑是否可以完整的覆蓋解空間,從而回推分治子問題定義的正確性。
* g(end) 表示 end 結尾的最長子陣列。
* 以 end 結尾,最長子陣列有兩種可能:g(end-1)+nums[end] , nums[end]
* 因此狀態轉移方程為:
* g(end) = max( g(end-1)+nums[end],nums[end])
* 回推一下,最長的子陣列一定是以 nums 中某乙個元素結尾的
* 最大值一定在 g(0)...g( length-1 ) 中
public轉為遞推表示:int maxsubarray(int
nums)
return
max;
}public
int dp(int nums, int end, int
cache)
if (cache[end] != 0)
cache[end] = math.max(dp(nums, end - 1, cache) +nums[end], nums[end]);
return
cache[end];
}
public最終解法效率:int maxsubarraydp(int
nums)
return
re; }
42 連續子陣列的最大和
hz偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天測試組開完會後,他又發話了 在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全為正數的時候,問題很好解決。但是,如果向量中包含負數,是否應該包含某個負數,並期望旁邊的正數會彌補它呢?例如 連續子向量的最大和為8 從第0個開始,到第...
42 連續子陣列的最大和
題目 hz偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天測試組開完會後,他又發話了 在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全為正數的時候,問題很好解決。但是,如果向量中包含負數,是否應該包含某個負數,並期望旁邊的正數會彌補它呢?例如 連續子向量的最大和為8 從第0個開始...
42 連續子陣列的最大和
hz偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天測試組開完會後,他又發話了 在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全為正數的時候,問題很好解決。但是,如果向量中包含負數,是否應該包含某個負數,並期望旁邊的正數會彌補它呢?例如 連續子向量的最大和為8 從第0個開始,到第...