最长等差数列
http://haixiaoyang.wordpress.com/category/dynamic-programming/
http://www.51nod.com/question/index.html#!questionId=79
在一個升序排列好的數(shù)列里面找到最長的等差數(shù)列
例子:1 3 5 6 8 9 10 12 13 14
子數(shù)列有(兩項的不在列舉)
1 3 5
1 5 9 13
3 6 9 12
3 8 13
5 9 13
.....
得出的最長的等差數(shù)列應(yīng)該是:6 8 10 12 14
方案1:
用hash
遍歷所有可能的差值d
? ?hash表中記錄的是到當(dāng)前為止,以之前的數(shù)字為結(jié)尾的等差數(shù)列的最長長度
? ?對一個新的元素,將其減去d之后,查找是否有相同的值,如果存在,則替換為這個新元素,并將值加1
public static void Solve1(int[] items) {Dictionary hash = new Dictionary();int max = items.Max() - items.Min();int maxLength = 2, maxInc = -1, last = -1;for (int inc = 1; inc < max; inc++){if (inc * maxLength > max)break;hash.Clear();hash.Add(items[0], 1);for (int i = 1; i < items.Length; i++){if (hash.ContainsKey(items[i] - inc)){int value = hash[items[i] - inc];hash.Remove(items[i] - inc);hash.Add(items[i], value + 1);if (value + 1 > maxLength){maxLength = value + 1;maxInc = inc;last = items[i];}}else if (!hash.ContainsKey(items[i]))hash.Add(items[i], 1);}}Console.WriteLine("{0} {1} {2}", maxLength, maxInc, last); }
方法2:
//Find the length of the longest arithmetic progression sequence of a sorted array//solution: //suppose there is the array a[n] with arithmetic progression: // ... a[i], a[j], a[k], use A[i][j] to symbol the number of arithmetic progression //starting from a[i], a[j], then A[i][j] = 1 + A[j][k], in which case //a[j] - a[i] == a[k] - a[j]; since the array is sorted, from each possible //middle point j, we can extend on left and right to seek out all pairs that make //a[i] - a[left] == a[right] - a[i]const int M = 15; int GetLPS(int a[M]) {assert(a);if (1 == M) return 1;int rec[M][M];for (int i =0; i < M; i++)for (int j = 0; j < M; j++)rec[i][j] = 2;int nMax = 2;for (int i = M - 2; i >= 1; i--){int nLft = i - 1;int nRgt = i + 1;while (nLft >= 0 && nRgt < M){if (a[i] - a[nLft] == a[nRgt] - a[i]){//one thing is if you iterate from left to right,//you should assign to rec[i][nRgt] rather than rec[nLft][i]rec[nLft][i] = rec[i][nRgt] + 1;if (rec[nLft][i] > nMax)nMax = rec[nLft][i];//well, the continuous same elements don't affect the result//why???nLft--, nRgt++; }else if (a[i] - a[nLft] < a[nRgt] - a[i])nLft--;else nRgt++;}}return nMax; }
設(shè)下標(biāo) j < i < k
f[i,k]表示以a[i], a[k]為等差數(shù)列的最后兩項的最長長度
如果 a[i]-a[j] = a[k] - a[i]則 f[i,k] = f[j,i] +1
又想到一種方法,但是很占內(nèi)存。f[i][k]表示以a[i]結(jié)尾的,差為k的數(shù)列的最大長度。
int getLArray(int *a, int n) {int maxDiff = a[n-1] - a[0];int ** f = new int *[n];for (int i = 0; i < n ; ++i)f[i] = new int [maxDiff+1];for (int i = 0; i < n ; ++i)for (int j = 0; j <= maxDiff; ++j)f[i][j] = 1;int maxLen = 2;for (int i = 1; i < n; ++i) {for (int j = i - 1; j >=0; --j) {int k = a[i] - a[j];if (f[i][k] < f[j][k] + 1)f[i][k] = f[j][k] + 1;if (maxLen < f[i][k])maxLen = f[i][k];}}for (int i = 0; i < n; ++i)delete [] f[i];delete []f;return maxLen; }
總結(jié)
- 上一篇: 找最大方阵
- 下一篇: 利用素数表快速寻找 n 以内的所有素数