NOIP-2013-J1-真题解析

一、选择题

1、A,基础题,考察基础数据类型,32位整型变量占4个字节
2、A,基础题,考察进制转换
3、B,算法题,考察递归算法的理解
4、C,数学题,考察逻辑运算,依次带入计算可得C
5、D,数据结构题,考察哈希表,哈希函数冲突情况检查,将序列元素,依次代入每个选项的哈希函数,计算函数值,若有相同的函数值,则会产生冲突,A,2,6,10,6,冲突,B,4,3,1,3,冲突,C,4,1,9,1,冲突,D,1,2,3,4,无冲突
6、B,基础题,十六进制,A-F分别表示10-15
7、B,数据结构题,考察对栈的理解
8、C,基础题,计算机基础操作
9、A,数据结构题,考察二叉树结点计算,10个结点的二叉树,当其是完全二叉树的时候,最多有4个结点有2个子结点
10、C,数据结构题,考察图的连通性,对于无向图,若要使图不连通,则至少要孤立出一个顶点,图中4个顶点的度都是3,任选一个顶点删除与其关联的3条边,即可将其孤立,使图不连通。
11、A,数据结构题,考察二叉树的遍历,先序遍历第一个访问的结点一定是根结点
12、A,考察图的深度优先搜索,以A0为起点,进行DFS,若紧接着遍历A1的话,则下一个遍历的只能是A3,最后是A2,选项A不可能
13、D,基础题,考察计算机网络常识,IPV6是128位地址
14、A,算法题,考察常见排序算法的平均时间复杂度,快速排序是O(nlogn),插入排序,冒泡排序均是O(n^2),基数排序是线性时间复杂度。
15、C,编程题,这里是经典的求两个数最大公约数的函数
16、C,基础题,计算机常识,搜索引擎应用常识
17、A,基础题,计算机网络常识,中国的国家顶级域名是.cn
18、D,编程题,考察数据强制类型转换,浮点数强制类型转换,若产生截断,是从低位截断的,高位包括符号位保留,若未产生截断,则数值不变,若原数正数,截断后将小于原数,若原数为负数,则将大于原数,但符号位是不变的,因此符号不可能变反。
19、A,编程题,考察do-while和while循环语句
20、B,竞赛常识题,CCF NOIP 复赛全国统一评测时使用的系统软件是NOI Linux

二、问题求解

1、数学题,考察排列组合,7个同学里任选2个有 C 7 2 = 21 C_7^2=21 C72=21种,排除相邻的有7种,剩余14种
2、数学题,题目给出5个问答可以依次推出密码,问答5,s1%2=0,故s1=0,问答1,s2%2=1,故s2=1,问答3,(1+s3)%2=0,故s3=1,问答2,(1+s4)%2=0,故s4=1,所以密码为:0,1,1,1

三、阅读程序

1、

#include <iostream>
using namespace std;
int main()
{
    int a, b;
    cin >> a >> b;
    cout << a << "+" << b << "=" << a + b << endl;
}

输入: 3 5
输出:3+5=8
2、

#include <iostream> 
using namespace std;
int main()
{
    int a, b, u, i, num;
    cin>>a>>b>>u; 
    num = 0;
    for (i = a; i <= b; i++)
        if ((i % u) == 0)
            num++;
    cout<<num<<endl; return 0;
}

输入: 1 100 15
编程题,考察for循环,求1-100之间,有多少个数是15的倍数,枚举可得,15,30,45,60,75,90,总共6个,输出为6
3、

#include <iostream> 
using namespace std;
int main()
{
    const int SIZE = 100;
    int n, f, i, left, right, middle, a[SIZE];
    cin>>n>>f;
    for (i = 1; i <= n; i++)
        cin>>a[i]; 
    left = 1;
    right = n; 
    do {
        middle = (left + right) / 2; 
        if (f <= a[middle])
            right = middle;
        else
            left = middle + 1; 
    } while (left < right); 
    cout<<left<<endl;
    return 0;
}

输入:
12 17
2 4 6 9 11 15 17 18 19 20 21 25
算法题,考察二分查找,这里是左边界查找,12个数中,查找第一个大于等于17的数的下标,注意数组元素下标是从1-12,所以是第7个数
4、

#include <iostream> 
using namespace std;
int main()
{
    const int SIZE = 100;
    int height[SIZE], num[SIZE], n, ans;
    cin>>n;
    for (int i = 0; i < n; i++) 
    { 
        cin>>height[i]; num[i] = 1;
        for (int j = 0; j < i; j++) 
        {
            if ((height[j] < height[i]) && (num[j] >= num[i]))
            num[i] = num[j]+1;
        }
    }
    ans = 0;
    for (int i = 0; i < n; i++)
    { 
         if (num[i] > ans) ans = num[i];
    }
    cout<<ans<<endl;
}

输入:
6
2 5 3 11 12 4
算法题,考察动态规划,问题是求最长上升子序列LIS的长度,num[i]表示以height[i]结尾的LIS长度,
num[i]=max{1, num[j]+1}
(j=1,2,…,i-1, && height[j]<height[i])
num[i]要么是只包含height[i],要么跟前面的LIS连起来,长度累加1,前提是前面的LIS的末尾元素比height[i]小,求出num[i]后,遍历num即可求出最长的LIS的长度,结果为4,LIS为2,3,11,12

三、完善程序

1、(序列重排)全局数组变量 a 定义如下:

const int SIZE = 100;
int a[SIZE], n;

它记录着一个长度为n 的序列 a[1], a[2], ⋯ , a[n]。 现在需要一个函数,以整数p (1 ≤p ≤n) 为参数,实现如下功能:将序列a 的前 p个数与后 n –p 个数对调,且不改变这p 个数(或n –p 个数)之间的相对位置。例如,长度为 5 的序列 1, 2, 3, 4, 5,当 p = 2 时重排结果为3, 4, 5, 1, 2 。 有一种朴素的算法可以实现这一需求,其时间复杂度为O( n)、空间复杂度为 O(n):

void swap1( int p )
{
    int i, j, b[SIZE];
    for ( i = 1; i <= p; i++ )
        b[] = a[i];             //  (3分)         
    for ( i = p + 1; i <= n; i++ )
        b[i - p] =;           //  (3分)    
    for ( i = 1; i <=; i++ )  //  (2分)
        a[i] = b[i];
}

我们也可以用时间换空间,使用时间复杂度为O(n^2)、空间复杂度为O(1) 的算法:

void swap2( int p )
{
    int i, j, temp;
    for ( i = p + 1; i <= n; i++ )
    {
        temp = a[i];
        for ( j = i; j >=; j-- )    //  ( 3 分)
            a[j] = a[j - 1];= temp;                     // ( 3 分)
    }
}

在这里插入图片描述

编程题,第一种方法,考察数组应用,这里用一个同等长度的临时数组b实现对调,如图所示,先将a的前p个元素依次放到b的后p个位置,再讲a的后n-p个元素依次放到b的前n-p个位置即可,注意循环赋值的左右边界即可。值时间复杂度为o(n),将数组a遍历一次即可,空间复杂度为o(n),用到临时数组。
① n-p+i,② a[i],③ n

在这里插入图片描述
这里的第二种算法对空间复杂度进行优化,实现就地对调,代价是时间复杂度提高到了 o ( n 2 ) o(n^2) o(n2),将前p个数整体进行右移,右移n-p次,每一次整体右移1个单位,逐个将这p个数往右覆盖,需要一个整型临时变量temp,暂存这p个数右端第一个被覆盖的元素,全部右移完后,将temp归位到这p个数左端,这样整体右移n-p次后即可。总共需要移动元素p(n-p)次,时间复杂度为 o ( n 2 ) o(n^2) o(n2),空间复杂度为o(1)。
④ i-p+1,将i-p到i-1位置的p个数,整体右移到i-p+1到i的位置,⑤ a[i-p],将a[i]归位到i-p的位置。

2、
(二叉查找树) 二叉查找树具有如下性质: 每个节点的值都大于其左子树上所有节点的 值、小于其右子树上所有节点的值。试判断一棵树是否为二叉查找树。 输入的第一行包含一个整数 n,表示这棵树有 n 个顶点, 编号分别为 1, 2, ⋯ , n,其 中编号为 1 的为根结点。之后的第 i 行有三个数 value, left_child , right_child ,分别表示该节点关键字的值、左子节点的编号、右子节点的编号;如果不存在左子节点或右子节点,则用 0 代替。输出 1 表示这棵树是二叉查找树,输出0 则表示不是。

#include <iostream> 
using namespace std; 
const int SIZE = 100;
const int INFINITE = 1000000;
struct node
{
    int left_child, right_child, value;
}; node a[SIZE];
int is_bst( int root, int lower_bound, int upper_bound )
{
    int cur;
    if ( root == 0 )
        return(1);
    cur = a[root].value;
    if ( (cur > lower_bound) && () && (is_bst( a[root].left_child, lower_bound, cur ) == 1) && (is_bst(,,) == 1) )
        return(1);
    return(0);
}


int main()
{
    int i, n; cin >> n;
    for ( i = 1; i <= n; i++ )
        cin >> a[i].value >> a[i].left_child >> a[i].right_child;
    cout << is_bst(, -INFINITE, INFINITE ) << endl;
    return(0);
}

数据结构题,此题作为压轴题相对简单,考察二叉查找树的判定,利用树的递归结构特点,采用递归进行判定,代码非常简洁工整,答案呼之欲出。
is_bst函数判断当前以root参数为根的树是否是二叉查找树,主函数从根节点开始调用is_bst,⑤ 1,根节点编号是1,初始左右子树最值分别是-INFINITE, INFINITE,调递归过程中,判断当前根节点的值是否大于左子树lower_bound,并且小于右子树upper_bound,并且左右子树都是二叉查找树,若是,则返回1,否则返回0

① cur<upper_bound,2,3,4根据已有代码也可以快速写出,②a[root].right_child, ③ cur,④ upper_bound

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

严老师编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值