动态数组练习题(一)

选择题

1.设入栈顺序为A,B,C,D,E则出栈序列不可能为(B)
A. EDCBA
B. ADEBC
C. ABCDE
D. ABDCE
解题思路:我们首先要知道栈遵守先进后出的原则。出栈的方式有多种,所以这个题我们可以用排除法:A选项先入栈的后出,出栈顺序符合;B选项A先出栈说明A刚进去就出栈,D出栈的话,说明B,C在D之前入栈,此时栈中顺序是BC,然后E进栈出栈,下来必然是C出栈,而不是B,所以B选项的出栈顺序不可能,选B,其他选项以此类推。
2.有六个元素6,5,4,3,2,1的顺序进栈,问下列哪一个不是合法的出栈序列(C)
A. 5 4 3 6 1 2
B. 4 5 3 1 2 6
C. 3 4 6 5 2 1
D. 2 3 4 1 5 6
解题思路:和第1题的类似,解法参考第1题
3.需要频繁的插入删除操作使用什么结构比较合适(C)
A. 数组
B. 队列
C. 链表
D. 栈
解题思路:此题是概念型题目。数组、队列、栈都是线性结构,所以查询快、插入删除满。链表是插入删除快,查询慢。
4.设栈S和队列Q的初始状态为空,元素e1,e2,e3,e4,e5和e6依次通过栈S,一个元素出栈后即进入队列Q,若6个元素出队的序列是e2,e4,e3,e6,e5,e1,则栈S的容量至少应该是(C)
A. 6
B. 4
C. 3
D. 2
解题思路:栈是先进后出,队列是先进先出,说明出队的序列也就是出栈的序列。e2先出,说明e1在栈中,栈中顺序为21,下来e4出,说明e3在栈中顺序为431,e6出,说明此时栈中顺序为651.所以栈容量至少为3
5.下列叙述中正确的是(A)
A. 在循环队列中,队头指针和队尾指针的动态变化决定队列的长度
B. 在循环队列中,队尾指针的动态变化决定队列的长度
C. 在带链的队列中,队头指针与队尾指针的动态变化决定队列的长度
D. 在循环队列中,队头指针一定小于队尾指针
解题思路:此题是概念型题目。循环队列中,队尾指针不能决定队列的长度,而且队头不一定小于队尾,所以BD排除。链表中指针指向的是节点的位置,队头和队尾指针之间没有关系,所以C排除。选A
6.设尾指针的循环链表表示队列,则入队和出队的时间复杂度均为O(1)(A)
A. 对
B. 错
解题思路:链表中入队和出队操作都只是移动指针,所以时间复杂度为O(1)
7.若进栈序列为a,b,c ,则通过入出栈操作可能得到的a,b,c的出栈的不同排列个数为(B)
A. 4
B. 5
C. 6
D. 7
解题思路:出栈的全部可能性,可以参考卡特兰数 n=(2n!) / (n! * (n+1)!)
8.循环队列的出队操作为(A)
A. sq.front = (sq.front+1) % maxsize;
B. sq.front = sq.front+1;
C. sq.rear = (sq.rear+1) % maxsize;
D. sq.rear = sq.rear+1;
解题思路:循环队列不管是入队操作还是出队操作,都要对最大容量进行取余,所以排除BD,C选项是入队操作,所以选A
9.采用计算机完成一个表达式的运算,常常需要判别一个表达式中左、右括号是否配对出现,这是实现的算法采用(D)数据结构最佳
A. 线性表的顺序存储元素
B. 队列
C. 线性表的链式存储结构
D. 栈
解题思路:当左括号进栈后,右括号在进栈之前进行对比,可以比较它们的ASCII值,如果符合,则配对成功。
10.循环队列的存储空间为Q(1:50),初始状态为front=rear=50。经过一系列正常的入队与退队操作后,front=rear=25,此后又插入一个元素,则循环队列中的元素个数为(A)
A. 1,或50且产生上溢错误
B. 51
C. 26
D. 2
解题思路:此题循环队列的rear指针是始终指向一个为null的空间。当rear=front时说明循环队列已空或已满,此时插入一个元素,个数为1或产生上溢错误。
11.现有初始状态均为空的栈X和队列Y,元素a,b,c,d,e,f,g依次进入栈X,每个元素出栈后即进入队列Y,如果出队的顺序为b,c,f,e,g,d,a,则要求栈X最小容量为(C)
A. 6
B. 5
C. 4
D. 3
解题思路:参考第4题
12.设有一个用数组Q[1…m]表示的环形队列,约定f为当前队头元素在数组中的位置,r为队尾元素的后一位置(按顺时针方向),若队列为空,则计算队列中元素的个数公式应为(A)
A. (m+r-f) mod m
B. r-f
C. (m-r-f) mod m
D. (m-r+f) mod m
解题思路:环形队列就是循环队列。计算循环队列中元素个数的公式:(rear - front + 表长)%表长
13.若用一个大小为6的数组来实现循环队列,队尾指针是rear,队头是front。当前rear和front的值分别为0和3,当从队列中删除一个元素,再加入两个元素后,rear和front的值分别为(B)
A. 1和5
B. 2和4
C. 4和2
D. 5和1
解题思路:注意rear指针始终指的是为null的空间,所以可以画图解题。
14.以下操作中,数组比链表速度更快的是(CE)
A. 原地逆序
B.头部插入
C. 返回中间节点
D. 返回头部节点
E. 选择随机节点
15.两个栈共享一片连续内存空间时,为提高内存利用率,减少溢出机会,应把两个栈的栈底分别设在这片内存空间的两端(A)
A. 对
B. 错
解题思路:把两个栈的栈底分别设在这片内存空间的两端就是双端栈
16.若有一个栈的输入序列时1,2,3,…,n,输出序列的第一个元素是n,则第i个输出元素是(C)
A. n-i
B. n-i-1
C. n-i+1
D. 不确定
解题思路:可以带值判断
17.设有一个长度为n的顺序表,要在第i(从1开始)个元素之前(也就是插入元素作为新表的第i个元素),则移动元素个数为(A)
A. n-i+1
B. n-i
C. n-i-1
D. i
解题思路:可以带值判断
18.对线性表采用折半查找,该线性表必须(A)
A. 元素按值有序排列
B. 采用顺序结构
C. 元素按值有序排列,并且采用顺序存储结构
D. 元素按值有序排列,并且采用链式存储结构

19.下面描述正确的为?(CD)
A. 线性表的逻辑顺序与物理顺序总是一致的
B.线性表的顺序存储表示优于链式存储表示
C. 线性表若采用链式存储表示时所有结点之间的存储单元地址可连续可不连续
D. 二维数组是其数组元素为线性表的线性表
解题思路:A选项不一致,B选项要看情况,C正确,D选项二维数组其实是一维数组中每个元素为一维数组的线性表,所以D正确
20.设栈的顺序存储空间为S(1:m),初始状态为top=m+1。现经过一系列正常的入栈与退栈操作后,top=0,则栈中的元素个数为(D)
A. 不可能
B. m+1
C. 1
D. m
解题思路:top=m+1说明此时top在栈底后面,当top=0的时候说明,栈已满,此时栈中元素个数为m

LeetCode算法题
905. 按奇偶排序数组

给定一个非负整数数组 A,返回一个数组,在该数组中, A 的所有偶数元素之后跟着所有奇数元素。
你可以返回满足此条件的任何数组作为答案。

示例:

输入:[3,1,2,4]
输出:[2,4,3,1]
输出 [4,2,3,1],[2,4,1,3] 和 [4,2,1,3] 也会被接受。

提示:

1 <= A.length <= 5000
0 <= A[i] <= 5000

解题思路:
①设置双指针:双指针分别指向头和尾,根据题意我们现在可以分为4种情况,
左偶右奇:元素不懂,指针移动;
左偶右偶:左边元素不动,指针后移,右边都不动;
左奇右奇:右边元素不动,指针前移,左边都不动
左奇右偶:元素相互交换,指针分别移动。

public int[] sortArrayByParity(int[] A) {

		/**
		 * 任何传进来的参数都有特殊情况
		 * 在没有参数说明之前最好进行判断
		 * 解法1:头尾交换
		 * 左偶右奇:L++ R--
		 * 左偶右偶:L++
		 * 左奇右奇:R--
		 * 左奇右偶:交换后是左偶右奇
		 */
		//A==null表示对象为空
		if(A==null || A.length==1 || A.length==0){
			return A;
		}
		int L=0;
		int temp=0;
		int R=A.length-1;
		while(L<R){
			if(A[L]%2==0&&A[R]%2==1){
				L++;
				R--;
			}else if(A[L]%2==0&&A[R]%2==0){
				L++;
			}else if(A[L]%2==1&&A[R]%2==1){
				R--;
			}else{
				temp=A[L];
				A[L]=A[R];
				A[R]=temp;
			}
		}
		return A;
	}

②双指针(插入排序):双指针i,j开始都指向同一位置,如果i指向的元素为奇数,不用管,i继续向后移。j一直指向i刚开始指向的元素,j和j-1相比,如果j-1为偶数或零时,j指向i的位置。如果j-1为奇数时,j和j-1交换位置,继续进行比较,直到j-1为偶数或零时结束。

		/**
		 * 解法2:不改变原先数字的相对顺序
		 * 输入:[3,1,2,4]
		 * 输出:[2,4,3,1]
		 * 冒泡排序O(n^2)
		 * 选择排序O(n^2)
		 * 插入排序O(n^2) 相对来说最快,是保证相对顺序
		 */
		int e=0;
		int j=0;
		for (int i = 1; i < A.length; i++) {
			if(A[i]%2==1){
				continue; //跳出本次循环,继续下一次循环
			}
			e=A[i];
			for (j = i; j > 0&&A[j-1]%2==1; j--) {
				A[j]=A[j-1];
			}
			A[j]=e;
		}
		return A;
169.求众数

给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在众数。

示例 1:

输入: [3,2,3]
输出: 3

示例 2:

输入: [2,2,1,1,1,2,2]
输出: 2

解题思路:
①连续相等数字个数+滑窗机制
先进行排序,让相等的数字连续。设置两个指针i和j,i是负责当前元素是谁,j负责当前元素的次数。当j指向的元素不等于i时,i就移动到j的位置。然后比较不同元素的次数。当i跳到某一个元素时,i所表示的角标大于n/2时,说明i就是众数,不用再继续比较下去了。

public int majorityElement(int[] nums) {
		/**
		 * 解法1:连续相等数字个数+滑窗思想
		 * 前提需要排序
		 */
		Arrays.sort(nums);//排序
		int count=0;
		int aim=0;
		int curCount=0;
		int curAim=0;
		int j=0;
		for (int i = 0; i < nums.length; ) {
			/**i表示的角标大于nums.length/2时
			 * 说明后面已经不可能有众数
			 * 所以不用继续比较了
			 **/
			if(i>(nums.length-1)/2){
				break;
			}
			curAim=nums[i];
			curCount=0;
			for (j = i+1; j < nums.length; j++) {
				if(nums[i]==nums[j]){
					curCount++;
				}else{
					break;
				}
			}
			if(curCount>count){
				count = curCount;
				aim=curAim;
			}
			i=j;
		}
		return aim;
    }

②消除
相当于有一个擂台,擂台上的元素与新上来的元素进行对比。如果相同,此元素数量增加;不同时,此元素数量减少。当擂台上的数量为0时,下一个元素就上擂台,此时元素数量为1,最后哪个元素在擂台上哪个就是众数

		/**
		 * 解法2:消除
		 */
		int num=nums[0]; //将第一个元素放到擂台上
		int count=1; //擂台上元素的数量
		for (int i = 1; i < nums.length; i++) {
			/**
			 * 新上台的元素与擂台上的元素相同时,数量增加
			 * 不同时,数量减少
			 * 当数量为0时,下一个元素就上擂台
			 */
			if(nums[i]==num){
				count++;
			}else{
				count--;
				if(count==0){
					num=nums[i];
					count=1;
				}
			}
		}
		return num;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值