《算法笔记》——入门篇习题简单模拟
第二天!!
第三章 入门篇(1)——入门模拟
【习题A】剩下的树
Problem Description
有一个长度为整数L(1<=L<=10000)的马路,可以想象成数轴上长度为L的一个线段,起点是坐标原点,在每个整数坐标点有一棵树,即在0,1,2,…,L共L+1个位置上有L+1棵树。
现在要移走一些树,移走的树的区间用一对数字表示,如 100 200表示移走从100到200之间(包括端点)所有的树。
可能有M(1<=M<=100)个区间,区间之间可能有重叠。现在要求移走所有区间的树之后剩下的树的个数。
Input
两个整数L(1<=L<=10000)和M(1<=M<=100)。
接下来有M组整数,每组有一对数字。
Output
可能有多组输入数据,对于每组输入数据,输出一个数,表示移走所有区间的树之后剩下的树的个数。
Sample Input
4 2
1 2
0 2
11 2
1 5
4 7
0 0
Sample Output
2
5
Thinking Notes
一、题目类型:
- 区间内删除元素,有重叠区间
二、变量设置
-
将元素设置成数组,记录0,1值,初值为0,对需要删除的区间内元素置1,最终统计0的个数即为剩下的
-
此处若赋初值为1,编译错误
三、代码设计
- while输入l和m到文件尾(while内增加条件判断:若m==0 break)
- 输入m组区间
- 区间内循环_如果为0则置1
- 区间内循环_统计为0的个数
- 输出统计值
Code Implementation(C)
#include<stdio.h>
int main(){
int l,m,z,y,flag[10001]={1},count=0;
while(scanf("%d %d",&l,&m)!=EOF){
int flag[10001]={0};
count=0;
if(m==0) break;//对于双输入(0 0)结束的单独控制
while(m--){
scanf("%d %d",&z,&y);
if(z>y){
int t;
t=z;
z=y;
y=t;
}
for(int i=z;i<=y;i++){
flag[i]=1;
}
}
for(int i=0;i<=l;i++){
if(flag[i]==0) count++;
}
printf("%d\n",count);
}
return 0;
}
Code Implementation(C++)
#include <cstdio>
#include <algorithm>//swap头文件
#include <cstring>//memset头文件
using namespace std;
int main(){
int l,m,z,y,flag[10001],sum=0;
while(scanf("%d%d",&l,&m)!=EOF){//连续输入:除了此种写法还可以:while(~scanf("%d%d",&l,&m))
sum=0;
memset(flag,0,sizeof(flag));//c++初始化,每次循环均初始化
if(m==0) break;//单独控制输入为0结束循环
while(m--){
scanf("%d%d",&z,&y);//输入m组区间
if(z>y)
swap(z,y);//根据输入示例看出应有控制zy大小顺序的语句
for(int i=z;i<=y;i++)
flag[i]=1;
}
for(int i=0;i<=l;i++)
if(flag[i]==0) sum++;
printf("%d\n",sum);
}
return 0;
}
【习题B】A+B
Problem Description
给定两个整数A和B,其表示形式是:从个位开始,每三位数用逗号","隔开。
现在请计算A+B的结果,并以正常形式输出。
Input
输入包含多组数据数据,每组数据占一行,由两个整数A和B组成(-109 < A,B < 109 )。
Output
请计算A+B的结果,并以正常形式输出,每组数据占一行。
Sample Input
-234,567,890 123,456,789
1,234 2,345,678
Sample Output
-111111101
2346912
Thinking Notes
一、题目类型:
- 从字符串中删除某些元素
二、变量设置
- 一个暂存数组temp(删除某些元素后的)
- 一个下标变量pos,用于记录保留下来的元素
if(a[i]!=',')//例如去除字符串中的’,‘
temp[pos++]=a[i];
}
三、代码设计
- dispose函数(杂质数组)
利用暂存数组去除某些杂质元素,返回干净数组 - 主函数
定义数组+初始化
循环输入字符串
调用dispose去除杂质
sscanf提取数字
输出和
初始化数组(避免存留脏数据)
四、字符数组的初始化方法
赋值方法 | 不同情况 | 逐个赋值 | 整体赋值 |
---|---|---|---|
固定数组长度 | 字符个数大于数组长度 | char str[3]={‘1’,’2’,’3’,’4’,’5’}; 错误 | char str[3]={“12345”}; 错误 |
- | 字符个数小于数组长度 | char str[10]={‘1’,’2’,’3’,’4’,’5’}; 系统自动填补\0 | char str[25] = "wo ai de ren bu ai wo." 系统自动填补\0 |
- | 字符个数等于数组长度 | char str[5]={‘C’,’h’,’I’,’n’,’a’}; 因系统不自动加\0,故合法 | char str[6]={“12345”}; 因系统自动加\0,定义数组长度时需要预留一个\0的空间 |
不固定数组长度 | - | char str[]={‘1’,’2’,’3’,’4’,’5’}; 因系统不自动加\0,故为了能通过strlen函数得到数组实际长度,初始化时需要人为加上\0,即char str[]={‘1’,’2’,’3’,’4’,’5’, ‘\0’}; | char str[]=“12345”; 或给字符串加上大括号:char str[]={“12345”}; 因系统自动填补\0,数组实际长度要加一 |
-
给单独的字符元素逐个赋值(单引号)不规定结尾为\0
1)固定数组长度
(1)如果字符个数大于数组长度,则按语法错误处理
(2)如果字符个数小于数组长度,系统自动填补
char str[10]={‘1’,’2’,’3’,’4’,’5’};
这种方法定义时,系统会自动从未初始化的元素开始,将之后的元素赋为\0,如上面的数组str中的元素实际上是:’1’,’2’,’3’,’4’,’5’,’\0’,’\0’,’\0’,’\0’,’\0’
(3)如果字符个数等于数组长度
char str[5]={‘C’,’h’,’I’,’n’,’a’};//字符常量用单引号,即把5个字符分别赋给str[0]到str[4]5个元素
单独逐个元素赋值时并不要求它的最后一个字符为’\0’,甚至可以不包含’\0’,这样写是完全合法的。
2)不固定数组长度
char str[]={‘1’,’2’,’3’,’4’,’5’};
这种方法定义时,系统不会自动在字符串的末尾加上字符串结束符;
此时用sizeof()函数可以正确求出其所占的内存大小;但用strlen()函数不能正确求出其长度,因为strlen是通过\0判断字符串结束的。
所以,采用该方法定义时,一般人为地加上\0,即char str[]={‘1’,’2’,’3’,’4’,’5’, ‘\0’}; -
字符串整体赋值(双引号)系统自动生成\0
1)不固定数组长度
char str[]=“12345”;
或给字符串加上大括号:
char str[]={“12345”};
这种方法定义时,系统会自动在字符串的末尾加上字符串结束符,即 ‘\0’,相应的数组长度也加一,是6,不是52)固定数组长度
char str[25] = "wo ai de ren bu ai wo."
这种方法定义时,系统会自动从未初始化的元素开始,将之后的元素赋为\0
因为系统回自动增加\0,所以在定义数组长度时要预留出一个\0的长度注意
上述这种字符数组的整体赋值只能在字符数组初始化时使用,不能用于字符数组的赋值,字符数组的赋值只能采用对其元素一一赋值的方法,下面的整体赋值方法是错误的
char str[ ];
str=“I am happy”;//错误,字符数组的赋值只能采用元素一一赋值的方法 -
总结
char str[]={“12345”}
//长度为6
等价于char str[]={‘1’,’2’,’3’,’4’,’5’, ‘\0’};
//长度6
不等价于char str[]={‘1’,’2’,’3’,’4’,’5’};
//长度5
五、关于字符和字符串
-
字符‘C’参与数字计算时的值为ascii码值
-
数组a[10]:数组长度10,下标从0~9
-
从字符串数组中提取出 整串数字字符 转换为 整型数字
sscanf(B,”%d”,&b);
//把字符串B转化成整数存储到b中 -
字符串数组中要把某个 数字字符元素 转换为 整型数字
A[I]-‘0’
Code Implementation(C++)
#include <cstdio>
#include <cstring>
using namespace std;
void dispose(char a[]){
char temp[16];//暂时保存去除逗号后的数组
memset(temp,'\0',sizeof(temp));//初始化为全\0
int pos=0;
for(int i=0;i<strlen(a);i++){
if(a[i]!=',') temp[pos++]=a[i];//此方法类似于逐个元素赋值,此时的系统会自动从未初始化的元素开始,将之后的元素赋为\0
}
for(int i=0;i<strlen(a);i++){//为什么不取temp数组(较短的长度)遍历呢?a的实际长度比temp长,所以相应的temp中的\0也被赋值到a中,将a中多余的旧数据用\0覆盖
a[i]=temp[i];
}
}
int main(){
char A[16],B[16];
memset(A,'\0',sizeof(A));
memset(B,'\0',sizeof(B));
while(scanf("%s %s",A,B)!=EOF){//字符串变量不用&
int a,b;
dispose(A);
dispose(B);
sscanf(A,"%d",&a);//sscanf函数:从字符串A中提取类型为d(整数)的内容存储到变量a中,即从A中输入a
sscanf(B,"%d",&b);//效果:把字符串A、B转化成整数存储到a、b中
printf("%d\n",a+b);
memset(A,'\0',sizeof(A));
memset(B,'\0',sizeof(B));//while循环和初始化的搭配写法
//memset(A,0,sizeof(A));
//memset(B,0,sizeof(B));
//给字符串数组初始化,用0和\0都行
}
return 0;
}