Topcoder:Zigzag 最长的大小交替子数组

来源:互联网 发布:酷狗音乐网络歌曲 编辑:程序博客网 时间:2024/06/11 00:25

在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;}

总结和牢骚:这道题是最长递增子序列LIS的变形。在LIS中只需要一个辅助数组用来保存当前最长的递增子序列的长度,但此题中子序列有两种情况,需要维护两个辅助数组。

还是自己的基础掌握不牢啊,没有迅速发现问题的本质。还需要多练啊!

0 0
原创粉丝点击