剑指offer-链表

【14 链表中倒数第k个节点】

题目描述

输入一个链表,输出该链表中倒数第k个节点。

思路:

1)如何创建链表:head指向链表头,设置两个指针,p为遍历指针,q为新节点指针,

2)判断链表为空,链表长度少于k个节点的情况

3)倒数第k个节点: 先行指针p先走k-1个指针,指向正序中第k个节点。q指向头节点,p,q同时开始往后遍历,p指向最后一个节点的时候,q所指向的节点就是倒数第k个节点。

struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) { //寻找倒数 第K个节点 
    ListNode *p=pListHead,*q=pListHead;
    int i=0;
    if(pListHead==NULL)		// 链表首先判断是否为空 
    	return NULL;
    for(i=0;i<k-1;i++)		
     // 利用两个指针p,q,p指针先遍历k-1个节点(指向第k个节点),q再开始遍历p到最后一个节点的位置,q指向倒数k个节点 
	{
		if(p->next!=NULL)
			p = p->next;
		else
			return NULL;
	}
	while(p->next!=NULL)
	{
		p = p->next;
		q = q->next;
	}
	return q; 
}

【15 反转链表】

题目描述

输入一个链表,反转链表后,输出新链表的表头。

思路:

1)反转链表,主要就是将指针的方向进行逆向,要小心保留遍历指针的位置。

ListNode* ReverseList(ListNode* pHead) {	//反转链表 
	ListNode *head=pHead,*q=pHead,*p=pHead;
	if(head==NULL||head->next==NULL)
		return head;
	p = head->next;  //遍历指针
	q = p;
	head->next=NULL;			// 头节点为反转链表的尾节点,需要指向NULL 
	while(q->next!=NULL) 
	{
		p = p->next; 		
	// head 记录反转链表的头部,q指向当前节点,p很重要,指向原链表的下一个位置,要在q->next之前先保留值,因为这边有p->next
	// 因此,while条件判断 p->next 或者q->next 为非空,是为了循环体内的 p->next 越界!!! 
		q->next = head;
		head = q;
		q = p;
	}
	//cout<<head->val<<"->"<<q->val<<"->"<<p->val<<endl; 
	q->next = head;
	head = q;
	return head;
}
//主函数,主要是链表的创建
int main()
{
	ListNode *head=NULL,*p,*q;
	int val,i,k;
	char c;
	p = head;
	while((c=cin.get())!='\n')  //根据输入值创建链表 节点 
	{
		cin.unget();
		cin>>val;
		q = (ListNode*)malloc(sizeof(ListNode));
		q->val = val;
		if(head==NULL)
		{
			head = q;
			//p = head;
		}	
		else
			p->next=q;
		p = q;
	}
	p->next = NULL;
	p = head;
	cin>>k;
	cout<<"List:"<<endl;
	while(p!=NULL)
	{
		cout<<p->val<<',';
		p=p->next;
	}
	cout<<endl; 
	q = FindKthToTail(head,k);
	cout<<"FindKthToTail:"<<q->val<<endl;
	
	p = ReverseList(head);
	cout<<"ReverseList:"<<endl;
	while(p!=NULL)
	{
		cout<<p->val<<',';
		p=p->next;
	}
	return 0;
}

【16-合并两个排序的链表】

题目描述

输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

思路:

1)判断是否出现某一条链表为空的情况

2)令List1为合并后的链表(p1指向开始节点小的那条链表)

      List1:指针p1为待插入的位置,p1->next为比较的节点,p2指向下一个位置

      List2:同理,有q1,q2

     合并时,比较p1->next与q1指向值大小,小于,则p1++;

       大于,修改p1的next指针,指向q1,修改q1的next指针,指向p1->next

3) 判断,List2 是否结束

ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
	ListNode *p1=pHead1,*p2,*q1=pHead2,*q2,*p;  
	if(pHead1==NULL)
		return pHead2;
	if(pHead2==NULL)
		return pHead1;  
	if(pHead2->val<pHead1->val)
	{
		p1 = pHead2; // p1指向最小节点的链表 
		q1 = pHead1;
	}
	p = p1;
	while(p1->next!=NULL)
	{
		//cout<<p1->val<<',';
		if(p1->next->val<=q1->val)
		{
			p1 = p1->next;
		}
		else
		{
			p2 = p1->next;
			q2 = q1->next;
			q1->next = p2;
			p1->next = q1;
			p1 = q1;
			q1 = q2;
		}	
		if(q1==NULL) 		//第二条链表先结束
			break;
	}  
	if(q1!=NULL)
	{	
		p1->next=q1;
	}
	return p;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值