这道题是网络中心某题。虽然简单但是有点点小心机,就是处理指针溢出的部分。
算法思想如下:
1 长度为n的数组要找到绝对增大的子数组要经过n-1次比较。
2 设置三个指针,一个记录子数组起始地址,一个记录终止地址,一个为比较数值的指针(总是在终止指针的下一个位置或者重合)
3 不断比较指针所指地址的值,若a[i]>=a[+1],则分是否为最后一次比较移动终止地址指针或者比较指针。不是最后一次,就三个都动;是最后一次,就三个都不动。
若a[i]<a[i+1],也分是否最后一次比较,若是,则移动终止指针,其他两个不动;若不是,则移动终止指针和比较指针。
4 用终止指针减去起始指针即子数组长度
分是否最后一次比较来移动指针,可以防止指针位置溢出
写算法加代码加不断调试竟然花了我快半小时QAQ,所以本代码可输入正整数、负整数。检测50组数内(自己可以改)数组的绝对增大子数组的长度。
#include<iostream>
#include<stdio.h>
using namespace std;
//找最大绝对连续增大的子数组的长度
int len=0; //数组长度初始为0,全局变量
int sublen=0;//子数组长度
int findlen(int a[], int* p)
{ /*需要三个指针,一个指针为记录绝对增大子数组的起始位置,一个指针为进行数值比较,一个指针记录子数组的末尾位置
长度为n的数组需要进行n-1次数值比较,同时最后一次比较需要特殊处理,否则指针会溢出存储区*/
int *j=p; //子数组末尾指针初始指向头指针
int *cmp=p+1; //比较指针初始位置为头结点的下一位
for(int i=1;i<len;i++) //只进行len-1次比较
{
if(*j>=*cmp) //没有自增
{
if(i==(len-1)) //最后一次比较还是无自增,则指针都不动否则会溢出
{}
else //不是最后一次则移动所有指针
{
cmp+=1;
j+=1;
p+=1;
}
}
else //有自增
{
if(i==(len-1)) //若是最后一次比较
{
j+=1; //只移动末尾指针
}
else
{
j+=1; //移动末尾指针
cmp+=1; //移动比较指针
}
}
}
sublen=j-p; //计算子数组长度
if(sublen!=0) sublen+=1;
return 0;
}
int main()
{
int str1[50]; //数组和普通的局部变量有区别
int *p=str1; //头结点指针
char c;
while(len<50) //输入不超过50个数字
{
c=getchar(); //获取输入字符
if((c>='0'&&c<='9')||c=='-') //输入正整数、负整数
{
ungetc(c,stdin);
cin>> str1[len++];
}
if(c=='\n') break; //换行则结束则结束输入
}
findlen(str1,p);
cout<<"the length is:"<<sublen<<endl;
return 0;
}
算法可能还有误差,但是大致思想应该没错。仅供参考。写到这里我发现确实有点问题,少考虑了情况,后面可能需要把所有增大子数组长度记录并选出最大。。。忘记考虑了。。。下次有时间写