《算法笔记》——入门篇习题简单模拟

第二天!!

第三章 入门篇(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,编译错误

三、代码设计

  1. while输入l和m到文件尾(while内增加条件判断:若m==0 break)
  2. 输入m组区间
  3. 区间内循环_如果为0则置1
  4. 区间内循环_统计为0的个数
  5. 输出统计值

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

三、代码设计

  1. dispose函数(杂质数组)
    利用暂存数组去除某些杂质元素,返回干净数组
  2. 主函数
    定义数组+初始化
    循环输入字符串
    调用dispose去除杂质
    sscanf提取数字
    输出和
    初始化数组(避免存留脏数据)

四、字符数组的初始化方法

赋值方法不同情况逐个赋值整体赋值
固定数组长度字符个数大于数组长度char str[3]={‘1’,’2’,’3’,’4’,’5’};错误char str[3]={“12345”};错误
-字符个数小于数组长度char str[10]={‘1’,’2’,’3’,’4’,’5’};系统自动填补\0char 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,数组实际长度要加一
  1. 给单独的字符元素逐个赋值(单引号)不规定结尾为\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’};

  2. 字符串整体赋值(双引号)系统自动生成\0
    1)不固定数组长度
    char str[]=“12345”;
    或给字符串加上大括号:
    char str[]={“12345”};
    这种方法定义时,系统自动在字符串的末尾加上字符串结束符,即 ‘\0’,相应的数组长度也加一,是6,不是5

    2)固定数组长度
    char str[25] = "wo ai de ren bu ai wo."
    这种方法定义时,系统会自动从未初始化的元素开始,将之后的元素赋为\0
    因为系统回自动增加\0,所以在定义数组长度时要预留出一个\0的长度

    注意
    上述这种字符数组的整体赋值只能在字符数组初始化时使用,不能用于字符数组的赋值,字符数组的赋值只能采用对其元素一一赋值的方法,下面的整体赋值方法是错误的
    char str[ ];
    str=“I am happy”;//错误,字符数组的赋值只能采用元素一一赋值的方法

  3. 总结
    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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值