现在的位置: 首页 > 综合 > 正文

最长等差数列

2018年12月13日 ⁄ 综合 ⁄ 共 2605字 ⁄ 字号 评论关闭

http://haixiaoyang.wordpress.com/category/dynamic-programming/

http://www.51nod.com/question/index.html#!questionId=79

在一个升序排列好的数列里面找到最长的等差数列

例子:1 3 5 6 8 9 10 12 13 14
子数列有(两项的不在列举)
1 3 5
1 5 9 13
3 6 9 12
3 8 13
5 9 13
.....

得出的最长的等差数列应该是:6 8 10 12 14


方案1:

用hash


遍历所有可能的差值d

   hash表中记录的是到当前为止,以之前的数字为结尾的等差数列的最长长度

   对一个新的元素,将其减去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;
}

设下标 j < i < k

f[i,k]表示以a[i], a[k]为等差数列的最后两项的最长长度

如果 a[i]-a[j] = a[k] - a[i]则 f[i,k] = f[j,i] +1

int maxDiffLen(int *a, int n) {
    vector<vector<int> > vt(n);
    for (int i = 0; i < n; ++i)
        vt[i].resize(n , 2 );

    int maxLen = 0;

    for (int i = 1; i < n - 1 ; ++i ) {
        int j = i - 1;
        int k = i + 1;

        while (j >= 0 && k < n) {
            if (a[k] - a[i] > a[i] - a[j]) --j;
            else if ( a[k] - a[i] < a[i] - a[j] ) ++k;
            else {
                vt[i][k] = vt[j][i] + 1;
                if (vt[i][k] > maxLen)
                    maxLen = vt[i][k];
                ++k;
                --j;
            }
        }
    } 
    
    return maxLen;
    

}

又想到一种方法,但是很占内存。f[i][k]表示以a[i]结尾的,差为k的数列的最大长度。


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;
}
【上篇】
【下篇】

抱歉!评论已关闭.