在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; }
还是自己的基础掌握不牢啊,没有迅速发现问题的本质。还需要多练啊!
Topcoder:Zigzag 最长的大小交替子数组,布布扣,bubuko.com
原文:http://blog.csdn.net/u012118523/article/details/24573947