Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 动态规划:仅使用一个dp数组查找锯齿形的最长子序列_Algorithm_Dynamic Programming - Fatal编程技术网

Algorithm 动态规划:仅使用一个dp数组查找锯齿形的最长子序列

Algorithm 动态规划:仅使用一个dp数组查找锯齿形的最长子序列,algorithm,dynamic-programming,Algorithm,Dynamic Programming,仅使用一个dp阵列可以解决此问题吗? 这是topcoder()的曲折问题 如果连续数字之间的差严格地在正负之间交替,则一个数字序列称为之字形序列。第一个差异(如果存在)可以是正的,也可以是负的。少于两个元素的序列通常是锯齿形序列 例如,1,7,4,9,2,5是一个之字形序列,因为差(6,-3,5,-7,3)交替为正和负。相反,1,4,7,2,5和1,7,4,5,5不是之字形序列,第一个是因为其前两个差值为正,第二个是因为其最后一个差值为零 给定一个整数序列sequence,返回序列中最长子序列的

仅使用一个dp阵列可以解决此问题吗? 这是topcoder()的曲折问题 如果连续数字之间的差严格地在正负之间交替,则一个数字序列称为之字形序列。第一个差异(如果存在)可以是正的,也可以是负的。少于两个元素的序列通常是锯齿形序列

例如,1,7,4,9,2,5是一个之字形序列,因为差(6,-3,5,-7,3)交替为正和负。相反,1,4,7,2,5和1,7,4,5,5不是之字形序列,第一个是因为其前两个差值为正,第二个是因为其最后一个差值为零


给定一个整数序列sequence,返回序列中最长子序列的长度,该子序列是一个Z字型序列。子序列是通过从原始序列中删除一定数量的元素(可能为零)而获得的,剩余的元素保持其原始顺序。

参考:具有两个数组的DP使用数组A[1..n],其中A[i]是以元素i上的之字形结尾的之字形序列的最大长度,而数组B[1..n]中的B[i]是以元素i上的锯齿形结尾的锯齿形序列的最大长度。对于从1到n的i,该DP使用A数组的先前条目来计算B[i],并使用B数组的先前条目来计算A[i]。以额外循环为代价,可以根据需要重新创建B条目,从而仅使用A数组。不过,我不确定这是否解决了你的问题


(另外,由于输入数组很短,因此有许多编码技巧不值得一提。)

这里是一个尝试,我将返回具有之字形的索引。在第二个输入(1,4,7,2,5)中,它返回5和4的索引,因为它是4,7,2,5的锯齿形

您可以根据结果判断整个阵列是否为之字形

 public class LongestZigZag
    {
        private readonly int[] _input;

        public LongestZigZag(int[] input)
        {
            _input = input;
        }

        public Tuple<int,int> Sequence()
        {
            var indices = new Tuple<int, int>(int.MinValue, int.MinValue);

            if (_input.Length <= 2) return indices;

            for (int i = 2; i < _input.Length; i++)
            {
                var firstDiff = _input[i - 1] - _input[i - 2];
                var secondDiff = _input[i] - _input[i - 1];

                if ((firstDiff > 0 && secondDiff < 0) || (firstDiff < 0 && secondDiff > 0))
                {
                    var index1 = indices.Item1;
                    if (index1 == int.MinValue)
                    {
                        index1 = i - 2;
                    }

                    indices = new Tuple<int, int>(index1, i);
                }
                else
                {
                    indices = new Tuple<int, int>(int.MinValue, int.MinValue); 
                }
            }

            return indices;
        }
    }
公共类最长之字形
{
专用只读int[]_输入;
公共长之字形(int[]输入)
{
_输入=输入;
}
公共元组序列()
{
var索引=新元组(int.MinValue,int.MinValue);
if(_input.Length 0&&secondDiff<0)| |(firstDiff<0&&secondDiff>0))
{
var index1=指数。项目1;
if(index1==int.MinValue)
{
index1=i-2;
}
索引=新元组(index1,i);
}
其他的
{
索引=新元组(int.MinValue,int.MinValue);
}
}
回报指数;
}
}

动态编程运行程序需要O(n2)个时间。我设计了一个线性时间复杂度O(n)的代码。通过数组中的一次遍历,它将给出最大可能序列的长度。我已经测试了许多由不同站点提供的测试用例,并得到了积极的结果

下面是我的C代码实现:

#include <stdio.h>
#include <stdlib.h>

int main()
{
int i,j;
int n;
int count=0;
int flag=0;
scanf(" %d",&n);
int *a;
a = (int*)malloc(n*sizeof(a));

for(i=0;i<n;i++)
{
    scanf(" %d",&a[i]);  //1,7,5,10,13,15,10,5,16,8
}   
i=0; 
if(a[0] < a[1])
{
    count++;
    while(a[i] <= a[i+1] && i<n-1)
    i++;

    if(i==n-1 && a[i-1]<a[i])
    {
        count++;
        i++;
    }    
}  
  while(i<n-1)
  {   count++;
      while(a[i] >= a[i+1] && i<n-1) 
      {
        i++;  
      }
      if(i==n-1 && a[i-1]>a[i])
      {
          count++; 
          break;
      }      
      if(i<n-1)
      count++;
      while(a[i] <= a[i+1] && i<n-1)
      {
          i++;
      } 
      if(i==n-1 && a[i-1]<a[i])
      {
          count++;
          break;
      }         
  }      

printf("%d",count);
return 0;
}     
#包括
#包括
int main()
{
int i,j;
int n;
整数计数=0;
int标志=0;
scanf(“%d”和“&n”);
int*a;
a=(int*)malloc(n*sizeof(a));
对于(i=0;i根据我对该主题的了解,所以不要想当然)您使用动态规划得出的每个解决方案,归结为用一个DAG(有向无环图)表示一个“解空间”(表示每个可能的解都是正确的,不一定是最优的)

例如,如果要查找最长的上升子项,则解空间可以表示为以下DAG:

  • 节点用序列号标记
  • 两个节点之间的边
    e(u,v)
    表示
    valueOf(u)
    (其中
    valueOf(x)
    是与节点
    x
    关联的值)
在动态规划中,找到问题的最优解与以正确的方式遍历该图是一样的。该图提供的信息在某种意义上由该DP数组表示

在本例中,我们有两个排序操作。如果我们在其中一个图上同时显示这两个操作,那么该图将不是非循环的-我们将至少需要两个图(一个表示

如果拓扑排序需要两个DAG,那么解决方案将需要两个DP数组,或者以某种巧妙的方式指示DAG中的哪个边对应于哪个排序操作(我认为这不必要地使问题复杂化)

因此,不,你不能只使用一个DP数组。你至少需要两个。至少如果你想要一个纯粹使用动态规划的简单解决方案


这个问题的递归调用应该是这样的(关系的方向可能是错误的,我没有检查):

S-给定序列(整数数组)
P(i),Q(i)-元素S[0->i]上最长之字形子序列的长度(正确的最长序列,其中S[i]是最后一个元素)
P(i)={如果i==0那么1

{max(Q(j)+1如果A[i]S - given sequence (array of integers) P(i), Q(i) - length of the longest zigzag subsequence on elements S[0 -> i] inclusive (the longest sequence that is correct, where S[i] is the last element) P(i) = {if i == 0 then 1 {max(Q(j) + 1 if A[i] < A[j] for every 0 <= j < i) Q(i) = {if i == 0 then 0 #yields 0 because we are pedantic about "is zig the first relation, or is it zag?". If we aren't, then this can be a 1. {max(P(j) + 1 if A[i] > A[j] for every 0 <= j < i)