2024年王道考研数据结构线性表—顺序表题目

第二章线性表 —— 顺序表

2.2.3 试题

选择题略
综合应用题
01: 从顺序表中删除最小值的元素(唯一)函数返回被删除的值,空出位置由最后一个元素补上,若表为空,显示错误信息并退出运行。

思路:遍历一遍,记录最小值和最小值的位置

bool solve(SqList &L,Elemtype &value)
{
	if(L.length==0)
	{
		return false;//返回值为0表示出现错误。 
	}
	int pos;
	value = L.data[0];
	for(int i=0;i<L.length;i++)
	{
		if(value > L.data[i])
		{
			value = L.data[i];
			pos = i;
		}
	}
	L.data[pos] =L.data[L.length-1];
	L.length--;
	return true;	
}
时间复杂度O(n),空间复杂度O(1)
02:设计算法,逆转顺序表L,要求空间复杂度为O(1)

思路:将两边挨个交换一下就行

void solve(SqList &L)
{
	int mid = (L.length)>>1;
	for(int i =0;i<mid; i++)
	{
		swap(L.data[i],L.data[L.length-i-1]);
	 } 
}
时间复杂度O(n),空间复杂度O(1)
03:设计一个算法删除线性表中所有值为X的元素,时间复杂度为O(n) , 空间复杂度为O(1);

思路:双指针法,一个first指针用于遍历线性表,一个second指针用于更新线性表的值,用新的表覆盖原先的表。

void solve(SqList &L,Elemtype x)
{ 
int first = 0, second = 0;//first用于遍历线性表,second用于存储需要的值 
while(first < L.length)
{
	if(L.data[first] != x)//不等于x将该值存放在L.data[second]中。 
	{
	L.data[second] = L.data[first];	
	second++;
	first++;
	}
	else
	{
		first ++;
	}
}
L.length = second; 
}
时间复杂度O(n),空间复杂度O(1)
04:设计一个算法从有序顺序表中删除在给定的s,t之间(s

思路:用first 和second 分别表示第一个大于s和第一个小于t的数,这两个之间便是要处理的数。

bool solve(SqList &L,Elemtype s,Elemtype t)
{ 
int first = 0, second = L.length-1;
if(s > t || L.length ==0 )
{
	return false;//返回false表示有错误
}
while(L.data[firs]<s||L.data[right]>t)//找到第一个大于s的地方存放在first第一个小于t的存放在second
{
	if(L.data[first]<s )first++;
	if(L.data[secodn]>t )second--;
}
if(first >= L.length || second <= 0 || first > second)//第一个大于s的在第一个小于t的数后面表示没有s-t中间的数字
{
	return true;//不用处理,表示已经结束 
}
while(second < L.length)
{
	L.data[first]=Ldata[second];
	first ++;
	second ++;
 } 
return true //表示处理结束
}
时间负载度为O(n) 空间复杂度为O(1);
05要求与上一题一致,只是有序变成无序

思路与03题类似,个人觉得比王道的答案更简单。

bool solve(SqList &L,Elemtype s,Elemtype t)
{ 
if(s > t || L.length ==0 )
{
	return false;//返回false表示有错误
}
int first = 0, second = 0;//first用于遍历线性表,second用于存储需要的值 
while(first < L.length)
{
	if(L.data[first] < s || L.data[first] > t )//不在s-t的范围内将其存储下来 
	{
	L.data[second] = L.data[first];	
	second++;
	first++;
	}
	else
	{
		first ++;
	}
}
L.length = second; 
return true;
}
时间复杂度O(n)空间复杂度O(1);
06从有序顺序表中删除所有重复元素,使表中元素都不相同。

思路双指针,判断first指向的值与second指向的值是否相等,不相等就存,相等就不存。

bool solve(SqList &L)
{ 
if( L.length ==0 )
{
	return false;//返回false表示有错误
}
int first = 1, second = 0;//first用于遍历线性表,second用于存储需要的值 

while(first < L.length)
{
	if(L.data[first]!=L.data[second] )//表示不是重复的值。
	{
	second++;
	L.data[second] = L.data[first];	
	first++;
	}
	else
	{
		first ++;
	}
}
L.length = second + 1; 
}
时间复杂度O(n)空间复杂度O(1);
07已知两个有序顺序表,设计算法将其合并并返回

bool solve(SqList &L1 , SqList &L2 , SqList &ans)
{

 if(L1.length + L2.length > ans.length) return false;
//合并后顺序表长度不够
	int first = 0 ,second =0,third = 0;
	while(first < L1.length && second < L2.length)
	{
		if(L1.data[first] < L2.data[second])
		{
			ans.data[third] = L1.data[first];
			third ++;
			first ++;
		}
		else
		{
			ans.data[third] = L2.data[second];
			third ++;
			second ++;
		}
	}
//将没存的残留数据存进去
	if(first <L1.length)
	{
		while(first < L1.length)
		{
			ans.data[third] = L1.data[first];
			third ++;
			first ++;
		}
	}
	if(second < L2.length)
	{
		while(second < L2.length)
		{
			ans.data[third] = L2.data[second];
			third ++;
			second ++;
		}
	}
	return true;
}

时间复杂度O(n)空间复杂度O(1);
08已知一维数组A[m+n]中一次存放两个线性表(a1,a2,a3…am)和(b1,b2,b3…bn),设计算法将两个线性表的顺序交换但是同一个线性表中数据的相对位置不变。变成(b1,b2,b3…bn)(a1,a2,a3…am);

思路:先将整个顺序表倒序,然后将前sum - m 个逆序,然后再将后面的sum - n个 逆序。

bool solve(SqList &L,int m)
{
 //传参给定顺序表L 以及 m表示前面a表的个数。
	for(int i = 0 ;i < (L.length>>1); i++ )//整个表倒序,将a和b的前后互换
	{
		swap(L.data[i],L.data[L.length - i - 1]);
	 } 
	 
	for(int i = 0 ; i< (L.length-m)>>1 ; i++)//将倒序的b再倒为正序
	{
		swap(L.data[i],L.data[L.length-m-i-1]);
	}
		for(int i =0; i< (m)>>1 ; i++)//将倒序的a再倒为正序
	{
		swap(L.data[L.length-m+i],L.data[L.length-i-1]);
	}
}

时间复杂度O(n)空间复杂度O(1);
09线性表(a1,a2 … an) 中的元素递增有序,切顺序存储,要求设计一个算法用最短的时间查询表中值为x的元素,若找到将其与其后继元素交换位置,若找不到则将其插入表中,使表仍然递增有序。

思路:二分查找

bool solve(SqList &L1,int x)
{ 
	int l = 0 , r = L1.length - 1;
	int mid = (l+r) >>1;//'>>'表示左移,也就是相当于除二
	while (l <= r)
	{
		mid = (l+r) >> 1;
		if( L1.data[mid] == x)
		{
			if(mid < L1.length-1)
			{
				swap(L1.data[mid],L1.data[mid + 1]);
			}
			//找到了就可以结束了
			return true; 
		}
		else
		if(L1.data[mid] < x) l = mid +1;
		else r = mid -1;
	}
    //二分查找得到的r表示的就是第一个比x小的数的所在的位置。
	for(int i = L1.length -1 ;i >r;i--)L1.data[i+1] = L1.data[i];
	L1.data[r+1] = x;
	L1.length++;
	return false;
	 
}

时间复杂度O(n)空间复杂度O(1);
10 设将 n(n>1)个整数存放到一维数组 R中。试设计一个在时间和空间两方面都尽可能高效的算法。将R 中保存的序列循环左移 p(0

①思路:就是和第八题几乎一模一样,a 和 b 的交换就相当于将整个数组左移了a的个数个位置,与本题的要求是一样的。

②代码

bool solve(SqList &L,int p)
{
 //传参给定顺序表L 以及 m表示前面a表的个数。
	for(int i = 0 ;i < (L.length>>1); i++ )//整个表倒序,将a和b的前后互换
	{
		swap(L.data[i],L.data[L.length - i - 1]);
	 } 
	 
	for(int i = 0 ; i< (L.length-p)>>1 ; i++)//将倒序的b再倒为正序
	{
		swap(L.data[i],L.data[L.length-m-i-1]);
	}
		for(int i =0; i< (p)>>1 ; i++)//将倒序的a再倒为正序
	{
		swap(L.data[L.length-m+i],L.data[L.length-i-1]);
	}
}

//分割线 其实这些操作是重复的,我们吧交换单独写一个多次调用也可以。
//---------------------------------------------------------

void reserve(SqList &L,int l , int r)
{
	int m = (r-l)>>1;
		for(int i =0; i<=(m) ; i++)//将倒序的a再倒为正序
	{
		swap(L.data[l+i],L.data[r-i]);
	}
}
void converse()
{
    reserve(L1,0,p-1);
	reserve(L1,p,L1.length-1);
	reserve(L1,0,L1.length-1);
}
时间复杂度O(n),空间复杂度O(1);
11一个长度为L(L≥1)的升序序列 S,处在第L/2(向上取整)个位置的数称为S 的中位数。

例如,若序列 S1=(11,13,15,17,19),则 S1 的中位数是 15,两个序列的中位数是含它们所有元素的升序序列的中位数。例如,若 S2= (2,4,6,8,20),则 S1 和 S2 的中位数是 11。现在有两个等长升序序列A和B,试设计一个在时间和空间两方面都尽可能高效的算法,找出两个序列A和 B 的中位数。要求:

思路:双指针分别表示两个序列的下标,寻找到两个序列的中位数就行了,因为是有序的所以就是第L/2(向上取整)个数就是中位数。

//方法一:这不是最优解 , 该方法是次优解,会扣一分,15分的题扣一分问题也不大了。
int solve(SqList &L1,SqList &L2)
{
		int x = (L1.length + L2.length)%2 ? (L1.length+L2.length)/2+1 : (L1.length+L2.length)/2;
        //三目运算符计算中位数的位置在哪儿
		int first = 0 , second = 0;
        //分别代指两序列的下标
		int ans = 0;
		while (first + second < x)
		{
			if(L1.data[first] <= L2.data[second])
			{
			ans = L1.data[first];
			first ++ ;	
			}	
			else
			{
				ans = L2.data[second];
				second ++ ;
			}
		} 
		return ans;
}
------------------------------------------------------
//法二:王道标准答案,用的是二分查找的思维方式,时间复杂度更低自己看书吧我懒得写了。

时间复杂度O(n)空间复杂度O(1);
12已知一个整数序列 A=(a1,a2,an),其中0<=ai

若存在ap1=ap2=···=apm=x且m>n/2(0Sp (0,5,5,3,5,7,5,5),侧5为主元素:又如4=(0,5,5,3,5,1,5,7),则A中没有主元素。假设 A 中的 n个元素保存在一个一维数组中,请设计一个尽可能高效的算法,找出A 的主元素。若存在主元素,则输出该元素:否则输出-1。

思路:如果到最后count大于0,那么代表k的个数要比n/2多count个

或者直接开另一个数组记录每个数字出现的次数,因为每个元素都大于0小于n;

//法一:更好想到
int solve(SqList &L1)
{
	int vis[L1.length];
    //因为数组是在函数里开的,所以需要初始化
	for(int i=0;i<L1.length;i++)
	vis[i] = 0
	//遍历序列
	for(int i= 0;i<L1.length;i++)
	{
		vis[L1.data[i]]++;
	}
	for(int i=0;i<L1.length;i++)
	{
	if(vis[i] > L1.length/2)return i;
	}
	return -1;
}
//时间复杂度O(n) , 空间复杂度O(n);这个答案只扣一分
----------------------------------------------
//方法二:这个是标准的答案,但是不容易想到
int solve(SqList &L1)
{
	int count = 1;
	int k = L1.data[0];
	for(int i=1;i<L1.length;i++)
	{
		if(L1.data[i] == k)
		{
			count++;
		}
		else{
			if(count > 0)count --;
			else
			{
				k = L1.data[i];
				count = 1;
			}
		}
	}
	if(count > 0)
	{
		for(int i=count=0;i<L1.length;i++)
		if(L1.data[i]==k)count++;
	}
	if(count>L1.length/2)return k;
	else return -1;
}
//时间复杂度O(n) 空间O(1);
13给定一个含n (n1) 个整数的数,请设计一个在时间上尽可能高效的算法,找出数组中未出现的最小正整数。例如,数组-5,3,2,3)中未出现的最小正整数是 1;数组{1,23)中未出现的最小正整数是 4。

思路:分配一个大小为n的b数组,b数组表示数字1- n出现与否,若数字i出现则b[i-1] = 1,如果刚好b数组全是1,则表示n+1是第一个为出现的正整数,否则i从0—n-1遍历,第一个b[i]==0表示第一个未出现的正整数是i+1,也说明,若0—n-1中存在未出现的值,则一定有答案在1-n中否则答案一定是n+1.

int solve(SqList &L1)
{
	int *b;
	b = (int *)malloc(sizeof(int)*L1.length);
	memset(b,0,sizeof(b));
	for(int i= 0 ;i<L1.length;i++)
	{
		if(L1.data[i]>0&&L1.data[i]<=L1.length)
		{
			b[L1.data[i]-1] = 1;
		}
	}
	for(int i=0;i<L1.length;i++)
	{
		if(b[i] == 0)return i+1;
	}
	retur
n L1.length+1;
}
//时间复杂度O(n)空间复杂度O(n);
14定义三元组 (a,b,c) (a,b,c 均为整数)的距离 D=|a-b| +|b-c|+|c-a|.给定3 个非空整数集合 S1,S2,S3按升序分别存储在 3 个数组中。请设计一个尽可能高效的算法,计算并输出所有可能的三元组 (a,b,c) (a∈S1,b∈S2,C∈S3) 中的最小距离。例如 S1=(-1,0,9),S2= {-25,-10,10,11},S3= {2,9,17,30,41) 则最小距离为 2,相应的三元组为 (9,10,9)

思路:D=|a-b| +|b-c|+|c-a| 放在平面上看其实就是最大最小值差的两倍,D = 2 *( max (a,b,c) - min(a,b,c)) 每次如果更新最大值或者第二大的值就会导致D必然变大或者不变,所以只需要更新最小的值。

int solve(SqList &L1,SqList &L2,SqList &L3)
{
int op1,op2,op3;
op1 = op2 = op3 = 0;
int ans = 2*(max(L1.data[op1],max(L2.data[op2],L3.data[op3])) - min (L1.data[op1],min(L2.data[op2],L3.data[op3])) );
while (op1 < L1.length && op2 < L2.length && op3 < L3.length && ans > 0)
{
	ans = min(ans ,(2*(max(L1.data[op1],max(L2.data[op2],L3.data[op3])) - min (L1.data[op1],min(L2.data[op2],L3.data[op3])) )));
	if(min(L1.data[op1],min(L2.data[op2],L3.data[op3])) == L1.data[op1]) op1 ++;
	else
	if(min(L1.data[op1],min(L2.data[op2],L3.data[op3])) == L2.data[op2]) op2 ++;
	else
	if(min(L1.data[op1],min(L2.data[op2],L3.data[op3])) == L3.data[op3]) op3 ++;
}
return ans;
}
时间复杂度O(n1+n2+n3)就是O(n) 空间复杂度为O(1);

后续会继续更新


你可能感兴趣的:(考研数据结构,考研,数据结构)