1、简述:
n个空间,存放a到a+n-1的数,位置随机且数字不重,a为正且未知,现在第一个空间的数被误设置为-1。
说明:已经知道被修改的数不是最小的。
例子:n=6,a=2,原始的串为5,3,7,6,2,4。现在被别人修改为-1,3,7,6,2,4。现在希望找到5。
思路:充分利用等差数列性质。
法一:开一全0的新数组,先找出被修改后的数中的最小值,然后让数组中的所有数依次减去这个最小值,所得的值作为另一个新数组的下标,将所有下标大于0的数组值赋为1,此时新数组中值为0的那个数就是被修改的数。
法二:找出被修改的数中的最小值和最大值,然后即可用等差数列求和公式求出所有数的和;再将空间中除-1外的所有数相加求和,将两种方法求得的和相比较,若相等则说明被修改的是最大值,若不等则差值即为被修改的数
法三:将空间中所有数从小到大排序,然后从-1之后挨个后数减前数,若差值大于1说明相减的两数间有被修改的数,若差值均等于1,说明被修改的是最大值。
程序:
#include <string.h>
#include <iostream.h>
unsigned int find_lost1(const int * source, const int length)//方法1求解
{
int i,n;
int *temp = new int[length];
memset(temp, 0, sizeof(int)*length);//将新数组初值全赋为0
int min, index;
for(i=0; i<length; i++)//任找一个非-1的数假设为最小值
if(source[i]!=-1)
{
min=source[i];
break;
}
for(i=0; i<length; i++)//找出数组中的最小值
{
if(min>source[i] && source[i]!=-1)
min=source[i];
}
for(i=0; i<length; i++)
{
index = source[i]-min;//将数组中的所有数分别减去最小值后所得的值作为新数组下标
if(index>=0)
temp[index]=1;//将新数组中下标大于0的元素赋值为1
}
for(i=0; i<length; i++)
{
if(temp[i]==0)//原数组中被替换的数以-1代,所以temp数组中对应值保持0不变
{
delete []temp;
n=i+min;//此时的下标值加上最小值即为被替换的数
}
}
return n;
}
unsigned int find_lost2(const int * source, const int length)//方法2求解
{
int i, min, max, sum1=0, sum2;
if(source[0]!=-1)//任找一个非-1的数假设为最小值和最大值
min=max=source[0];
else
min=max=source[1];
for(i=0; i<length; i++)
{
if(source[i]!=-1)
{
if(min>source[i]) min=source[i];//找出数组中的最小值
if(max<source[i]) max=source[i];//找出数组中的最大值
sum1+=source[i];//将数组中非-1的值加起来求和(即去除被替换数的其他所有数之和)
}
}
sum2 = (max-min+1)*(min+max)/2;//用等差数列求和公式求和
if( sum1 == sum2)//两种方法所求的和相等,说明被替换数是原数组中的最大值
return (max+1);
else
return (sum2-sum1);//若两种方法所求的和不相等,则相减得被替换的数
}
unsigned int find_lost3(const int * source, const int length)//方法3求解
{
int i,j,temp;
int *source1=new int[length];
memcpy(source1,source,length*sizeof(int));//因为形参中的const无法对原数组中数据直接排序,所以将其拷贝到一个新数组中
for(i=0;i<length-1;i++)//在新数组中将原数组中数据按冒泡法由小到大排序
{
for(j=0;j<length-i-1;j++)
{
if (source1[j]>source1[j+1])
{
temp=source1[j];
source1[j]=source1[j+1];
source1[j+1]=temp;
}
}
}
/*从非-1的数开始,后数减前数,因为是等差数列,差值必为1,若不为1则两数之间是被替换的数*/
temp=0;
for (i=1,j=2;i<length-1,j<length;i++,j++)//因为-1在首位,所以下标从1开始
{
if(source1[j]-source1[i]!=1)
{
temp=source1[i]+1;//前数加上等差1即为被替换的数
break;
}
}
if(temp==0)//temp为0说明被替换的数是原数组中的最大值
temp=source1[length-1]+1;
return temp;
}
void main()
{
int a[]={4, 3, 7, 8, 5, -1, 2};
int loc;
loc=find_lost1(a, sizeof(a)/sizeof(a[0]));
cout<<"方法1,丢失的数是:"<<loc<<endl;
loc=find_lost2(a, sizeof(a)/sizeof(a[0]));
cout<<"方法2,丢失的数是:"<<loc<<endl;
loc=find_lost3(a, sizeof(a)/sizeof(a[0]));
cout<<"方法3,丢失的数是:"<<loc<<endl;
}
2、简述:给定一个c++代码文件,输出去掉注释后的文件内容。
说明:注释可以使用“/* */”和“//”,其语义为c++语义。注意处理两种注释混用的情况。
程序:
#include <string.h>
#include <stdio.h>
#include <iostream.h>
void foo(const char *src, char *buf, unsigned int buf_len)
{
int i=0, j=0;
int len = strlen(src);
while(i<len && j<buf_len)
{
if(src[i]=='/' && (i+1)<len && src[i+1]=='/')//判断是否为'//'注释符
{
i+=2;//若是'//'注释符则定位到其后
while(src[i]!='/n') i++;//若没遇到回车则一直往后读
i++;//跳过回车,定位到其后
}
else
if( src[i]=='/' && (i+1)<len && src[i+1]=='*')//判断是否为'/*'注释符
{
i+=2;//若是'/*'注释符则定位到其后
while(src[i]!='*' || ( (i+1)<len && src[i+1]!='/'))
i++;//若没遇到下一个'*/'注释符则一直往后读
i+=2;//跳过'*/'注释符,定位到其后
}
else
{
buf[j++] = src[i++];//将去除注释符后的内容拷贝到缓冲区中
}
}
}
void main()
{
char path[]={"c://1.cpp"};
FILE *file;
if( (file=fopen(path, "r+")) != NULL)
{
int len;//file 的长度
fseek(file, 0L, SEEK_END);
len=ftell(file);
fseek(file,0,SEEK_SET);
char *src=new char[len+1];
char *buf=new char[len+1];
memset(src,0,len+1);
memset(buf,0,len+1);
if(!feof(file))
fread(src,len,sizeof(char),file);
fclose(file);
foo(src,buf,len);
cout<<src<<endl;
cout<<buf<<endl;
delete []src;
delete []buf;
}
}