笔试强训03|字符串中找出连续最长的字符串|数组中出现次数超过一半的数字(C++)

单选
1.单选

以下程序的输出结果是()

#include <stdio.h> 
main() 
{ 
	char a[10] = {'1', '2', '3', '4', '5', '6', '7', '8', '9', 0};
	char *p; 
	int i; 
	i = 8; 
	p = a + i; 
	printf("%s\n", p - 3); 
}

A. 6
B. 6789
C. ‘6’
D. 789

解析
  • 定义了一个字符数组,大小为10,并且进行了初始化
  • 声明了一个char类型的指针变量,和一个int类型的一个整形变量i,i赋值为8
    • p=a+i:a是一个数组名,也是一个指针常量,是指向数组首元素的,+i的话也就是+8,就是向后偏移8个指针类型的大小,指针类型是char,向后偏移8个字节,指针p指向字符9
    • print是将从p-3的地址处,使用%s格式化打印,p变量是指向字符9的,p-3向前偏移3个指针类型大小,也就是从6开始向后进行%s打印,遇到\0才会停止打印
  • 所以会将6789打印出来,遇到\0停止打印
  • 选B

2.单选

以下程序的输出结果是()

#include <iostream.h>
int main() 
{ 
	int x=3,y=3; 
	switch(x%2) 
	{ 
	case 1: 
		switch (y) 
		{ 
		case 0: 
			cout<<"first"; 
		case 1: 
			cout<<"second"; 
			break; 
		default: 
			cout<<"hello"; 
		} 
	case 2: 
		cout<<"third"; 
	} 
	return 0; 
}

A. second third
B. hello
C. first second
D. hellothird

解析
  • x变量初始化为3,y变量也初始化为3
  • switch语句:里面的表达式是x%2=1,进入case1语句
  • 里面又是一个switch语句,表达式是y,y的值是3,不会进入case0和1语句,会进入default语句,输出hello,结束这个switch语句
  • 因为case1没有break语句,所以不会跳出外层这个switch语句,继续向下执行,直到遇到第一个break语句,或者整个switch语句运行结束,跳出switch语句,所以会继续向下执行case2语句,输出third
  • 结果是hellothird
  • 选D

3.单选

以下能对二维数组a进行正确初始化的语句是()
A. int ta[2][]={{0,1,2},{3,4,5}};
B. int ta[][3]={{0,1,2},{3,4,5}};
C. int ta[2][4]={{0,1,2},{3,4},{5}};
D. int ta[][3]={{0,,2},{},{3,4,5}};

解析

A:二维数组在声明的时候,行可以省略,列不可以省略
B:省略了行,没有省略列,所以是正确答案
C:声明的是两行四列,但初始化的时候初始化了三行,每个大括号就是一行
D:初始化部分有问题,初始化的时候必须连续初始化,中间不能有间隔

  • 选B

4.单选

把函数处理结果的二个数据返回给主调函数,在下面的方法中不正确的是()
A. return这二个数
B. 形参用数组
C. 形参用二个指针
D. 用二个全局变量

解析

A:return的时候每次只能return一个数据类型,两个数据是不能return的,除非放到一个数组或容器里面返回
B:用数组的话,在调用函数的时候,需要传递数组的地址,将函数处理的结果放在数组当中,函数调用完以后,可以通过访问数组来获取处理结果
C:两个指针,在调用函数的时候需要传入两个地址变量,将对应的处理结果放在地址的所指空间,在函数调用完以后,主调函数通过两个指针去访问所指空间的值
D:全局变量作用域在整个源文件都是有效的,在这个函数处理完以后,主调函数可以对全局变量进行访问,获取处理结果

  • 选A

5.单选

int *p[4] 与选择项中的() 等价
A. int p[4]
B. int *p
C. int *(p[4])
D. int (*p)[4]

解析
  • int *p[4]:方括号的运算优先级高于星号,p和方括号先结合,表示它是一个数组,数组里面存放的是int类型的指针,所以它是int类型的指针数组,数组大小为4
    A:是一个整形数组,大小为4
    B:是一个int类型的指针
    C:p是和方括号先结合,表示它是一个数组,里面存放的是int类型的指针,符合题意
    D:先和星号去结合,表示是一个指针,是一个数组指针,数组里面存放的是int类型,大小为4
  • 选C

6.单选

设变量已正确定义,以下不能统计出一行中输入字符个数(不包含回车符)的程序段是
A. n=0;while(ch=getchar()!='\n')n++;
B. n=0;while(getchar()!='\n')n++;
C. for(n=0;getchar()!='\n';n++);
D. n=0;for(ch=getchar();ch!='\n';n++);

解析

A:把n初始化为0,有个while循环,条件判断部分是用getchar获取一个字符,将字符赋值给ch变量,再和\n去比较,如果是\n就结束循环,如果不是\n则进行n++,也就是统计字符。第一个字符和\n去比较,不是就n++,直到遇到\n结束循环,此时n的值就是字符的个数
B:没有将getchar获取的值赋给ch,而是直接和\n进行比较,也是可以的
C:用的for循环,初始化部分,n初始化为0,条件判断部分,getchar获取一个字符和\n进行比较,如果不等于\n,则进行循环操作,循环操作完了以后n++,也就是说,当不等于\n,则n++,若等于\n,则结束循环
D:在for循环外面初始化n为0,for循环的初始化部分获取一个字符,for循环的初始化部分只会进行一次,所以for循环只会获取一次字符,不可能去遍历每个字符,去统计,所以不符合题意

  • 选D

7.单选

以下代码

char *ptr; 
char myString[] = "abcdefg"; 
ptr = myString; 
ptr += 5;

代码执行之后ptr指向的内容是?
A. Compiler error
B. f
C. efg
D. defg

解析
  • 声明了一个char类型的指针变量ptr,还有一个指针数组,使用字符串初始化,
  • ptr初始化,指向数组的地址,数组首元素的地址指向a,
  • ptr+=5,向后偏移5个类型大小,因为是char类型,向后偏移5个字节,指向f,因为是char类型的,指向f这个字母
  • 选B

8.单选

下面3段程序代码的效果一样吗()

int b; 
(1)const int *a = &b; 
(2)int const *a = &b; 
(3)int *const a = &b;

A. (2)=(3)
B. (1)=(3)
C. (1)=(2)
D. 都不一样

解析
  • 是用const修饰的指针变量,
  • 常量指针,所指空间的值是一个常量,不能发生改变,不能通过指针解引用修改指针所指空间的值,但是指针的指向可以发生改变
  • 指针常量,指针是一个常量,不能改变指针的指向,但是可以指针解引用改变所指空间的值
  • 区分const和星号运算符的相对位置,const在*左边就是常量指针,否则就是指针常量
  1. const修饰的是int,并且在星号左边,是一个常量指针,
  2. const同样在星号左边,是一个常量指针
  3. const在星号右边,是一个指针常量
    1和2效果是一样的
  • 选C

9.单选

32位系统中,定义**a[3][4],则变量占用内存空间为()。
A. 4
B. 48
C. 192
D. 12

解析

32位系统,

  • **a[3][4]:方括号的运算符高于星号,a先和方括号进行结合,表示它是一个数组,是一个3行4列的二维数组,存放的是指针类型,
  • 3行4列有12个元素,指针类型在32位系统中,每一个指针占4个字节,总共是4*12=48个字节
  • 选B

10.单选

假设在一个 32 位 little endian 的机器上运行下面的程序,结果是多少?

#include <stdio.h>
int main()
{ 
	long long a = 1, b = 2, c = 3; 
	printf("%d %d %d\n", a, b, c); 
	return 0; 
}

A. 1,2,3
B. 1,0,2
C. 1,3,2
D. 3,2,1

解析

大小端

  • 大端是低位存高地址
  • 小端是低位存低地址
    int i= 1;
  • 从左到右是从低地址向高地址增长
    大端:00 00 00 01
    小端:01 00 00 00
    long long类型占8个字节,将a,b,c三个变量的地址写出来
    a:01 00 00 00 00 00 00 00
    b:02 00 00 00 00 00 00 00
    c:03 00 00 00 00 00 00 00
    通过printf函数去打印这三个变量的值,
    printf是一个库函数,在调用函数的时候,会创建一个函数栈帧,因为是栈,是从高地址向低地址增长,先从高地址开始开辟空间,往低地址去延伸,并且这个函数在调用的时候变量是从右往左入栈的,也就是c,b,a的顺序
    先将c变量入函数调用栈
//低地址      <<<<---------------------------------     高地址
01 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00
  • 三个变量入栈以后,再进行打印,是%d进行打印的,每次获取4个字节内存的数据,采用10进制整数的形式打印,
  • 栈是一个先进后出的容器,最后入的最先出,先打印a变量,会从内存中获取四个字节的数据进行打印,也就是01 00 00 00,作为a的值打印出来,再向后找00 00 00 00打印b的值,依次找四个字节,02 00 00 00来打印c,
  • 转换为10进制,就是1,0,2
  • 选B

编程
1. 编程题

字符串中找出连续最长的数字串_牛客题霸_牛客网 (nowcoder.com)
知识点
字符串 贪心 模拟

题目
  • 描述
    读入一个字符串str,输出字符串str中的连续最长的数字串
  • 输入描述:
    个测试输入包含1个测试用例,一个字符串str,长度不超过255。
  • 输出描述:
    在一行内输出str中里连续最长的数字串。
  • 示例1
    输入:
    abcd12345ed125ss123456789
    输出:
    123456789 -
思路
  • 给一个例子ab12a 1a 456e,连续最长的应该是456
    • 分别定义cur和ret两个字符串,
  • i从字符串0下标开始去往后遍历,如果i在走的过程当中,i下标是一个数字字符,就把它放到cur字符串中;如果不是就继续往后遍历
    • 此时将1和2放入cur字符串中
    • 再往后走发现a是非数字字符,此时cur里面存放的是12,
    • ret用来存放结果,cur存起来的和ret去比较,去比较size(),如果cur比ret的size大,此时ret是0,cur是2,就把cur的内容拷贝到ret里
    • 下一个数字串是1,把1放到cur里,再往下走遇到a,将cur的size和ret的size相比较,cur小于ret就把cur的内容清掉,cur.clear()
    • 以此类推往后走,遇到456放入cur,遇到e,cur的size比ret大,将cur的内容拷贝覆盖到ret里
  • ret里一直存放的是最长的,直到i遇到\0结束,此时ret里存放的就是所要求的结果
代码
#include <iostream>
#include <string>
using namespace std;

int main()
{
	string str, cur, ret;

	// 获取用户输入的字符串
	cin >> str;

	//通过i来遍历当前的字符串,i的范围是从0到字符串的长度(包括字符串末尾的'\0')
	for (int i = 0; i <= str.length(); i++)
	{
		//判定遍历的字符是否是数字
		if (str[i] >= '0' && str[i] <= '9')
		{
			// 如果是数字字符,则将其添加到当前数字串cur中
			cur += str[i];
		}
		// 如果遇到的字符不是数字字符,则进行以下操作: 
		// 如果当前数字串cur的长度大于之前记录的最长数字串ret的长度,则更新ret为cur
		else
		{
			if (ret.size() < cur.size())
			{
				ret = cur;
			}
			else
			{
				// 否则清空当前数字串cur,以便记录下一个数字串
				cur.clear();
			}
		}
	}
	// 输出最长的数字串
	cour << ret << endl;
}

注意
for (int i = 0; i <= str.length(); i++)

  • 这里的i必须是<=str.length,当\0前面一位是数字而不是字母时,如ab12a 1a 456,当i遍历到6时,cur里是45,i=length-1,<length,进入到if循环里,将6也拼接到cur中,再进行i++,到\0,i=str.length,这时不进入循环,最长的应该是456,但cur并没有拷贝覆盖到ret里
  • 当i=\0时,\0不是大于0小于9的数字,斜杠0和字符0不一样,if进不去,走else,会判断ret和cur的size,ret比cur小,将cur的内容拷贝覆盖到ret里,走完这次循环,i++,超出length范围,循环结束,此时ret存放的是最长的

2. 编程题

数组中出现次数超过一半的数字_牛客题霸_牛客网 (nowcoder.com)
技能
数组 哈希

题目
  • 描述
    给一个长度为 n 的数组,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
    例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。
  • 数据范围:n≤50000,数组中元素的值 0≤val≤10000
  • 要求:空间复杂度:O(1),时间复杂度 O(n)
  • 输入描述:
    保证数组输入非空,且保证有解
    示例1
    输入:
    [1,2,3,2,2,2,5,4,2]
    返回值:
    2
    示例2
    输入:
    [3,3,3,3,2,2,2]
    返回值:
    3
    示例3
    输入:
    [1]
    返回值:
    1
思路一
  • 输入一个数组,里面的数字是无序的,12322
  1. 对整体进行排序,12223,发现数组中间的数字是2,并且是出现次数超过一半的数字
  2. 找到中间的数字,x,
    2
  3. 再次遍历这个数组,看x出现了多少次,是否大于数组长度的一半
    发现2出现了3次,超过了数组长度的一半,
    如果大于找到答案
思路二
把出现次数超过数组一半的数字称为众数,其他数字称为非众数
如果两个数不相等,就消去这两个数
最坏的情况下,每次消去一个众数和一个非众数,如果存在众数,最后留下的数肯定是众数
  1. 分别定义两个变量,一个是result(最终结果),一个是times(出现次数),用i来进行遍历,对于1来说,出现了依次,i从数组的第二个位置开始,判断当前数字和前面的数字是否相同,相同就让times++,不相同让times–,
  2. i从1下标开始,进入循环以后需要将times分为等于0和不等于0两种情况
    如果times不等于0
    这个数是1,和下标0的数字相同,times++
    这个数是2,和下标0的数字不相同,times–,把众数和非众数消掉
    如果times等于0
    把这个数赋给result,times置为1
  3. 此时result=3,times=0
  4. i走到2,因为times!=0,2!=3,所以times=0
  5. 下一个还是2,把这个数赋给result,此时result=2,times=1
  6. 再往后走,i超过数组的长度,此时result最终存的数字2,就是众数
    最后拿到2之后,判断2到底是不是众数
    如果最后一个数是1的话,虽然result存的是1,但是1不是众数
    如果这组数字里面没有众数,最后存住的数字就不是众数
    如果存在众数,最后留下的数字一定是众数
  7. 最后遍历依次数组,看最后留的数字出现的次数是不是超过数组长度的一半
代码
思路一
class Solution {
public:
	// MoreThanHalfNum_Solution 函数用于找出给定数组中出现次数超过一半的元素
    int MoreThanHalfNum_Solution(vector<int>& numbers) {
	    // 如果数组为空,则直接返回0
		if(numbers.empty()) 
			return 0;

		// 对数组进行排序,以便找到中间位置的元素
		sort(numbers.begin(), numbers.end());
		// 获取中间位置的元素作为候选元素
		int midNum = numbers[numbers.size()/2];
		// 统计候选元素在数组中出现的次数
		int count = 0;
		for(int i = 0; i < numbers.size(); i++)
		{
			// 如果当前元素与候选元素相等,则计数器加一
			if (midNum == numbers[i])
			{
				count++;
			}
		}
		// 如果候选元素出现的次数超过数组长度的一半,则返回候选元素,否则返回0
		if (count > number.size()/2)
		{
			return midNum;
		}
		return 0;
    }
};

这段代码是一个类 Solution 中的一个成员函数MoreThanHalfNum_Solution,用于找出给定的整数数组中出现次数超过数组长度一半的元素。它采用了排序和计数的方法来实现:首先对数组进行排序,然后找到排序后中间位置的元素作为候选元素,最后遍历数组统计候选元素的出现次数,如果超过了数组长度的一半,则返回该候选元素,否则返回0。

思路二
class Solution {
public:
    int MoreThanHalfNum_Solution(vector<int>& numbers) {
	    // 如果数组为空,则直接返回0
		if(numbers.empty()) 
			return 0;

		// 初始化候选元素为数组的第一个元素,并初始化计数器为1
		int result = numbers[0];
		int times = 1;

		// 遍历数组,找出出现次数最多的元素
		for (int i = 1; i < numbers.size(); i++)
		{
			// 如果计数器不为零,则更新候选元素和计数器
			if (times != 0)
			{
				// 如果当前元素与候选元素相等,则计数器加一,否则减一
				if (numbers[i] == result)
				{
					++times;
				}
				else
				{
					--times;
				}
			}
			// 如果计数器为零,则更新候选元素和计数器
			else
			{
				result = numbers[i];
				times = 1;
			}
		}
		//遍历数组,统计候选元素在数组中的出现次数,看result中的值是不是众数
		times = 0;
		for (int i = 0; i < numbers.size(); i++)
		{
			if (numbers[i] == result)
			{
				times++;
			}
		}
		// 如果候选元素出现的次数超过数组长度的一半,则返回候选元素,否则返回0
		if (times > numbers.size()/2)
		{
			return result;
		}
		return 0;
    }
};

  • 18
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值