数据结构算法题整理4

1.仅有头指针,查找输出倒数第k个元素。

基本思想是设置两个指针p、q均指向链表的第一个数据结点,p沿着链表移动,q先不动,设置一个计数器count初值为0,count随着p的移动而增加,当count的值为k时,p和q一起移动,当p移动到最后一个结点时,q指针所指的就是倒数第k个结点。可以自己画个图出来试试。仅仅遍历一遍就找到了元素k。最容易想到的办法就是,直接遍历一遍,数出有多少个元素,然后再根据元素位置去查找,这样会至多增加一半的时间复杂度。算法效率不高。

typedef in ElemType;
typedef struct LNode{
	ElemType data;
	struct Lnode *next;
}*LinkList;

int Search_k(LinkList list, int k)
{
	//查找链表的倒数第k个结点并输出
	LinkList p=list->next,q=list->next;
	int count=0;
	while(p!=NULL)
	{
		if(count<k) count++;
		else q=q->next;p=p->next;  //注意这个地方p=p-next;语句不在判断之中始终执行
	}
	if(count<k)
		return 0;
	else {
		printf("%d",q->data);
		return 1;
	}
}

2.将有n(n>1)个整数的数组R中保存的数据循环左移P位。

基本思想是将数组分为两部分,两部分分别逆序,再整体逆序即为所得

void Reverse(int R[],int from,int to){
	int i, temp;
	for(i=0;i<(to-from+1)/2;i++)
	{
		temp=R[from+i];
		R[from+i]=R[to-i];
		R[to-i]=temp;
	}
}

void Converse(int R[], int n,int p)
{
	Reverse(R,0,p-1);
	Reverse(R,p,n-1);
	Reverse(R,0,n-1);
}

//算法时间复杂度为O(n),空间复杂度为O(1)

3.求两个有序序列合起来的中位数。

基本思想是根据归并后的结果来判断,设A序列的中位数为a,B序列的中位数为b。如果原先的两个序列中位数相等,那么合并之后的中位数一定是a或者b,容易理解,因为归并后的序列 原先排在ab前面的数归并后一定排在ab的前面,原先排在ab之后的数归并后一定排在ab的后面,ab一定是位于整个序列的中间,那么归并后的中位数一定是a或者b。
如果a<b,那么中位数一定位于序列a到b之间的某个数,因此可以将a之前的数和b之后的数舍弃掉,再从a到b之间去找,同样的可以再从两部分序列中分别找出中位数再比较,重复下去,直到两个序列只含有一个元素为止,则较小的即为所求的中位数。
如果a>b,那么中位数一定位于b到a之间的某个数,因此可以将b之前的数舍弃掉,a之后的数舍弃掉,从a,b之间去找,再剩下的序列中重复上述过程,直到两个序列中只有一个元素,则较小的为中位数。

注意,这里只是假定序列归并了,如果真的归并有序了那么中位数肯定就是数组中间的数,就不用麻烦这么半天了,这样做虽然算法简单,但是效率不高。

int M_Search(int A[],int B[],int n)
{
	int s1=0,d1=n-1,m1,s2=0,d2=n-1,m2;
	while(s1!=d1 || s2!=d2)
	{
		m1=(s1+d1)/2;
		m2=(s2+d2)/2;
		if(A[m1]==B[m2])
			return A[m1];
		if(A[m1]<B[m2])
		{
			if((s1+d1)%2==0)
			{
				s1=m1;
				d2=m2;
			}
			else
			{
				s1=m1+1;
				d2=m2;
			}
		}
		else{
			if((s1+d1)%2==0){
				d1=m1;
				s2=m2;
			}
			else{
				d1=m1+1;
				s2=m2;
			}
		}
	}
	return A[s1]<B[s2]? A[s1]:[s2];
}
//算法的时间复杂度为O(nlog2n),空间复杂度为O(1)

4.找两个链表的公共链表的起始位置,这两个链表的末端指向了同一个链表。

基本思想是先遍历两个链表求出链表长度,让两个链表末端对齐,对于更长的链表,指针可以先多移动m-n个距离,让两个指针平齐,然后两个指针一起向后遍历,反复比较它们指向的结点的next指针是否相同,若相同则找到。

LinkNode *Find_lst_Common(LinkList str1,LinkList str2)
{
	int len1=Length(str1),len2=Length(str2);
	LinkNode *p,*q;
	for(p=str1;len1>len2;len1--)
		p=p->next;
	for(q=str2;len1<len2;len2--)
		q=q->next;
	while(p->next!=NULL && p->next!=q->next)
	{
		p=p->next;
		q=q->next;
	}
	return p->next;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值