在topcoder上闲逛,看到了这个题,就索性做了一下。
题意:zigzag序列是指数组中连续元素之间的差正负交替,第一个差(若存在)可正可负,只有一个元素时也可被看成是一个zigzag序列。
例如:1,7,4,9,2,5是一个zigzag序列,因为连续元素之间的差值为6,-3,5,-7,3正负交替。1,4,7,2,5和1,7,4,5,5不是zigzag序列,因为前者的前两个差值为3,3;后者后一个差值为0。
给一个整数数组,求出这个数组中的最长zigzag子数组的长度。
例如:
{ 1, 7, 4, 9, 2, 5 }返回6;{ 1, 17, 5, 10, 13, 15, 10, 5, 16, 8 }返回7。
不会做这道题,借鉴了一下网上的思路。
思路:
因为以A[i]结尾的zigzag子序列有两种情况:A[i]前面的元素比A[i]小;A[i]前面的元素比A[i]大,因此以A[i]结尾存在这两种子序列,要求以A[i]结尾的zigzag子序列的长度,需要开辟两个辅助数组用以记录这两种情况下的最大长度:
up[i]表示以A[i]结尾的,并且A[i]比所在的zigzag子序列中前一个元素大时的最长子序列的长度;
down[i]表示以A[i]结尾的,并且A[i]比所在的zigzag子序列中前一个元素小时的最长子序列的长度。
up[i]和down[i]初始值均为1。
up[i] = max(up[i], down[j] + 1),0 <= j < i && A[j] < A[i];即在原数列的A[i]前面的所有小于A[i]的元素中找出down[]值最大的一个,使其down值加1;
down[i] = max(down[i], up[j] + 1),0 <= j < i && A[j] > A[i];即在原数列的A[i]前面的所有大于A[i]的元素中找出up[]值最大的一个,使其up值加1。
因此以A[i]结尾的最长的zigzag子序列的长度为max(up[i],down[i])。然后从每个元素的最长zigzag子序列长度中选择最大的一个返回。
思路理清之后再写代码会顺利许多:
size_t len_zigzag(int *A,size_t n)
{
if(A == NULL)
return 0;
int *down = new int[n];
int *up = new int[n];
for(size_t i = 0; i < n; i++)
{
down[i] = 1;
up[i] = 1;
}
size_t result = 1;
for(size_t i = 1; i < n; i++)
{
size_t maxdown = 0;
size_t maxup = 0;
for(size_t j = 0; j < i; j++)
{
if(A[j] > A[i] && maxdown < up[j])
{
maxdown = up[j];
}
if(A[j] < A[i] && maxup < down[j])
{
maxup = down[j];
}
}
down[i] = maxdown + 1;
up[i] = maxup + 1;
int max = down[i] > up[i] ? down[i] : up[i];
result = result > max ? result : max;
}
delete []up;
delete []down;
return result;
}
还是自己的基础掌握不牢啊,没有迅速发现问题的本质。还需要多练啊!