從某種角度來說是沒有暴力算法這個算法或者所有的題都是暴力。
所謂的暴力算法就是不考慮空間複雜度和時間複雜度以及代碼長度直接通過題意而不經過大腦思考而直接完成題。
暴力的題一般很簡單沒有什麼要講的,但是如果想改進暴力算法就要學習很多種算法思想以及算法代碼。
暴力題最好的辦法就是多做題,但是以後學習其他算法後要結合其他算法來完成之前暴力所做的題纔能有所進步!
問題描述
- 求一個序列的最大子段和即最大連續子序列之和。例如序列[4, -3, 5, -2, -1, 2, 6, -2]的最大子段和爲11=[4+(-3)+5+(-2)+(-1)+(2)+(6)]。
-
1. 暴力算法
- 思想:從序列首元素開始窮舉所有可能的子序列。
- 代碼示例
#include<stdio.h> int MaxSubsequenceSum(const int array[], int n) { int tempSum, maxSum; maxSum = 0; for (int i = 0;i < n;i++) // 子序列起始位置 { for (int j = i;j < n;j++) // 子序列終止位置 { tempSum = 0; for (int k = i;k < j;k++) // 子序列遍歷求和 tempSum += array[k]; if (tempSum > maxSum) // 更新最大和值 maxSum = tempSum; } } return maxSum; } int main() { const int a[] = { 4, -3, 5, -2, -1, 2, 6, -2 }; int maxSubSum = MaxSubsequenceSum(a, 8); printf("The max subsequence sum of a is: %d " ,maxSubSum ); system("pause"); return 0; }
- 算法複雜度O(n3)
4. 動態規劃的算法
原問題:考慮最大子段和原問題:給定nn個數(可以爲負數)的序列(a1,a2,...,an)(a1,a2,...,an),求max{0,max1≤i≤j≤n∑jk=iak}max{0,max1≤i≤j≤n∑k=ijak}
子問題界定:設前邊界爲1,後邊界爲ii,且C(i)C(i)是子序列A[1,..i]A[1,..i]必須包含元素A[i]A[i]的向前連續延伸的最大子段和:
C[i]=max1≤k≤i{∑j=kiA[j]}
C[i]=max1≤k≤i{∑j=kiA[j]}遞推方程滿足:
C[i]=max{C[i−1]+A[i], A[i]}i=2,...,nC[1]={A[1] ifA[1]>00 ifA[1]<0
C[i]=max{C[i−1]+A[i], A[i]}i=2,...,nC[1]={A[1] ifA[1]>00 ifA[1]<0
遍歷所有以i (1≤i≤n)i (1≤i≤n)爲後邊界的最大子段和CiCi得出最優解:
OPT(A)=max1≤i≤n{Ci}
OPT(A)=max1≤i≤n{Ci}
核心代碼:
int MaxSubsequenceSum(const int A[], int n)
{
int tempSum = 0;
int maxSum = 0;
for (int j = 0;j < n;j++) // 子問題後邊界
{
tempSum = (tempSum + A[j]) > A[j] ? (tempSum + A[j]) : A[j];
if (tempSum > maxSum) // 更新最大和
maxSum = tempSum;
}
return maxSum;
}
- 算法複雜度爲O(n)。
所以說暴力算法可以解決很多問題,但是如果比賽時候故意卡你的時間複雜度或者空間複雜度就需要學習其他算法。最後說一遍暴力算法提升最快的方法就是多做題同時學習自己不會的知識,當你的思維和基礎達到一定高度,就不需要天天刷水題來浪費生命,這時配合其他算法就會使你的編程能力得到飛速提升!