几道简单的链表题

1.删除链表指定值

题目简介

给你一个链表的头节点head和一个整数 val ,请你删除链表中所有满足Node.val == val的节点,并返回新的头节点 。
在这里插入图片描述
LeetCode 203

思路分析

创建一个新链表,将原链表中所有数值不是val的结点尾插到新链表上。

代码实现

struct ListNode* removeElements(struct ListNode* head, int val){
    if(head==NULL)
        return NULL;
    
    struct ListNode* newhead=NULL,*tail=NULL;
    struct ListNode* cur=head;
    while(cur)
    {
        struct ListNode* next=cur->next;
        if(cur->val==val)
        {
            free(cur);
        }
        else
        {
            if(tail==NULL)
            {
                newhead=tail=cur;
            }
            else
            {
                tail->next=cur;
                tail=cur;
            } 
        }
        cur=next;
    }

    if(tail)
        tail->next=NULL;
    
    return newhead;
}

2.反转一个单链表

题目简介

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

在这里插入图片描述
LeetCode 206

思路分析

思路一:调整前后指针的指向。
思路二:创建一个新链表,将原链表头插到新链表上

代码实现

//思路一
struct ListNode* reverseList(struct ListNode* head){
	//空链表
	if (head == NULL)
		return NULL;

	struct ListNode* n1, *n2, *n3;
	n1 = NULL;
	n2 = head;
	n3 = head->next;

	while (n2)
	{
		n2->next = n1;
		n1 = n2;
		n2 = n3;
		if (n3)
			n3 = n2->next;
	}
	return n1;
}

//思路二
struct ListNode* reverseList(struct ListNode* head){
    struct ListNode* cur = head;
	struct ListNode* newnode = NULL;
    //头插
    while(cur)
    {
        struct ListNode* next=cur->next;
        cur->next=newnode;
        newnode=cur;
        cur=next;
    }
    return newnode;
}

3.找链表中间结点

题目简介

给定一个头结点为 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。

在这里插入图片描述
LeetCode 876

思路分析

利用快慢指针,快指针一次走两步,慢指针一次走一步,当快指针走到尾结点时,慢指针正好在中间结点处

代码实现

struct ListNode* middleNode(struct ListNode* head){
    struct ListNode* fast,*slow;
    fast=slow=head;
    //找结点
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
    }
    return slow;
}

4.找倒数第K个结点

题目简介

在这里插入图片描述
牛客网

思路分析

创建快慢指针,快指针先走K步,然后快慢指针一起走,当快指针走到尾结点时,慢指针的位置正好是倒数第K个结点的位置

代码实现

struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
	// write code here
	struct ListNode* fast, *slow;
	fast =slow =pListHead;
	while (k--)
	{
		if (fast == NULL)
			return NULL;
		fast = fast->next;
	}

	while (fast != NULL)
	{
		fast = fast->next;
		slow = slow->next;
	}

	return slow;
}

5.合并两个有序链表

题目简介

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

在这里插入图片描述
LeetCode 21

思路分析

创建一个新链表,比较两个链表结点的值,将较小值尾插到新链表上。

代码实现

struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){

    //判断l1是否为NULL,若是直接返回l2
	if (l1 == NULL)
		return l2;
      
	if (l2 == NULL)
		return l1;

	struct ListNode* n1 = l1, *n2 = l2;
	struct ListNode* newhead = NULL, *tail = NULL;

	//取一个较小值做头结点
	if (n1->val<n2->val)
	{
		newhead = tail = n1;
		n1 = n1->next;
	}
	else
	{
		newhead = tail = n2;
		n2 = n2->next;
	}

    //尾插
	while (n1&&n2)
	{
		if (n1->val<n2->val)
		{
			tail->next = n1;
			tail = tail->next;
			n1 = n1->next;
		}
		else
		{
			tail->next = n2;
			tail = tail->next;
			n2 = n2->next;
		}
	}

    //n1为NULL时,直接将n2剩下结点尾插
	if (n1)
		tail->next = n1;
        
	if (n2)
		tail->next = n2;

	return newhead;
}

6.求相交链表的相交结点

题目简介

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

在这里插入图片描述
LeetCode 160

思路分析

先计算两个链表的长度,并取其差值的绝对值,让长链表先走差值步,然后两链表同时走,当两链表结点相同时,该结点就为相交结点

代码实现

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct ListNode* curA=headA;
    struct ListNode* curB=headB;
    int lenA=0,lenB=0;
    while(curA)
    {
        ++lenA;
        curA=curA->next;
    }
    while(curB)
    {
        ++lenB;
        curB=curB->next;
    }

    struct ListNode* LongList=headA;
    struct ListNode* ShortList=headB;
    if(lenA<lenB)
    {
        LongList=headB;
        ShortList=headA;
    }

    //让长的走差距步
    int gap=abs(lenA-lenB);
    while(gap--)
    {
        LongList = LongList->next;
    }

    //同时走找交点
    while(ShortList && LongList)
    {
        if(ShortList==LongList)
        {
            return ShortList;
        }
        ShortList=ShortList->next;
        LongList=LongList->next;
    }

    //不相交
    return NULL;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值