链表中倒数第k个节点 | 合并两个有序链表

举报
跳动的bit 发表于 2022/04/25 07:53:15 2022/04/25
【摘要】 1.链表中倒数第k个节点<难度系数⭐>📝 题述:输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。💨 示例:给定一个链表: 1->2->3->4->5, 和 k = 2.返回链表 4->5🧷 平台:Visual studio 2017 && windows🔑 核心思想:快慢指针,快指针先走k步,此时它与慢指针相差的就...

1.链表中倒数第k个节点<难度系数⭐>

📝 题述:输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。

💨 示例:
给定一个链表: 1->2->3->4->5, 和 k = 2.
返回链表 4->5
在这里插入图片描述
🧷 平台:Visual studio 2017 && windows

🔑 核心思想:
快慢指针,快指针先走k步,此时它与慢指针相差的就是k步,然后快慢指针同时1步1步的走,直到快指针指向NULL,此时慢指针指向的节点就是目标节点
请添加图片描述

leetcode原题
牛客网原题

⚠ 这道题我在两个平台都做了下,按照常规的写法,发现它在leetcode能过的代码,在牛客网上却过不了

请添加图片描述
所以我们这里使用更严格的写法

#include<stdio.h>
#include<stdlib.h>

typedef int SLTDataType;

struct ListNode
{
	int val;
	struct ListNode *next;
};
struct ListNode* getKthFromEnd(struct ListNode* head, int k)
{
	if(k == 0)
        return NULL;
	struct ListNode *slow, *fast;
    slow = fast = head;
    //fast先走k步
    while(k--)
    {
		//如果k大于链表的长度
        if(fast == NULL)
            return NULL;    
        fast = fast->next;
    }
    //slow和fast同时走,直至fast指向空
    while(fast)
    {
        slow = slow->next;
        fast = fast->next;
    }
    
    return slow;
}
int main()
{
	struct ListNode* n1 = (struct ListNode*)malloc(sizeof(struct ListNode));
	n1->val = 1;

	struct ListNode* n2 = (struct ListNode*)malloc(sizeof(struct ListNode));
	n2->val = 2;

	struct ListNode* n3 = (struct ListNode*)malloc(sizeof(struct ListNode));
	n3->val = 3;

	struct ListNode* n4 = (struct ListNode*)malloc(sizeof(struct ListNode));
	n4->val = 4;

	struct ListNode* n5 = (struct ListNode*)malloc(sizeof(struct ListNode));
	n5->val = 5;
	
	n1->next = n2;
	n2->next = n3;
	n3->next = n4;
	n4->next = n5;
	n5->next = NULL;

	getKthFromEnd(n1, 2);
	return 0;
}

2.合并两个有序链表<难度系数⭐>

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

💨 示例1:
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

💨 示例2:
输入:l1 = [], l2 = []
输出:[ ]

💨 示例3:
输入:l1 = [ ], l2 = [0]
输出:[0]

在这里插入图片描述

🧷 平台:Visual studio 2017 && windows

🔑 核心思想:
思路1,见下图
请添加图片描述
思路2,带哨兵位的头节点
请添加图片描述
在之前的文章中没有了解过什么是哨兵位头节点,在这里就了解下:
在这里插入图片描述

1️⃣ 哨兵位头节点,这个节点不存储有效数据;而非哨兵位头节点存储有效数据

2️⃣ 非哨兵位头节点如果要修改头指针,需要使用二级指针操作;而哨兵位头节点,则不会修改头指针,因为它不存储有效数据

3️⃣ 这种哨兵位头节点在实际中很少出现,包括哈希桶、临接表做子结构都是不带头的。其次就是OJ中给的链表都是不带头的(从上面做的这些题就可以看出),所以我们在以后编码过程中,应该尽量使用不带头的

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>

typedef int SLTDataType;

struct ListNode
{
	int val;
	struct ListNode *next;
};
//思路1
struct ListNode* mergeTwoLists1(struct ListNode* l1, struct ListNode* l2)
{
	struct ListNode *n1 = l1, *m1 = l2;
	struct ListNode *newhead = NULL, *tail = NULL;
	//判断空链表
    if(l1 == NULL)
        return l2;
    if(l2 == NULL)
        return l1;
        
	while(n1 && m1)
	{
		if(n1->val < m1->val)
		{
			if(newhead == NULL)
			{
				newhead = tail = n1;
			}
			else
			{
				tail->next = n1;
				tail = n1;
			}	
			n1 = n1->next;		
		} 
		else
		{
			if(newhead == NULL)
			{
				newhead = tail = m1;
			}
			else
			{
				tail->next = m1;
				tail = m1;
			}
			m1 = m1->next;
		}
	}
	//链接上剩余的数据
    if(n1)
        tail->next = n1;
    if(m1)
        tail->next = m1;
        
    return newhead;
}
//思路2
struct ListNode* mergeTwoLists2(struct ListNode* l1, struct ListNode* l2)
{
	struct ListNode *n1 = l1, *m1 = l2;
	struct ListNode *newhead = NULL, *tail = NULL;
    //判断空链表
    if(l1 == NULL)
        return l2;
    if(l2 == NULL)
        return l1;
    //申请空间
    newhead = tail = (struct ListNode*)malloc(sizeof(struct ListNode));
	while(n1 && m1)
	{
		if(n1->val < m1->val)
		{
			tail->next = n1;
			tail = n1;	
			n1 = n1->next;		
		} 
		else
		{
			tail->next = m1;
			tail = m1;
			m1 = m1->next;
		}
	}
    //链接上剩余的数据
    if(n1)
        tail->next = n1;
    if(m1)
        tail->next = m1;
    //这里返回的是不带哨兵位的头节点。其次malloc开辟了空间,就要主动释放,否则会内存泄漏
    struct ListNode* first = newhead->next;
    free(newhead);
    return first;
}
int main()
{
	struct ListNode* n1 = (struct ListNode*)malloc(sizeof(struct ListNode));
	n1->val = 1;

	struct ListNode* n2 = (struct ListNode*)malloc(sizeof(struct ListNode));
	n2->val = 2;

	struct ListNode* n3 = (struct ListNode*)malloc(sizeof(struct ListNode));
	n3->val = 4;

	n1->next = n2;
	n2->next = n3;
	n3->next = NULL;
	/*----------------------------------分割------------------------------------*/
	struct ListNode* m1 = (struct ListNode*)malloc(sizeof(struct ListNode));
	m1->val = 1;

	struct ListNode* m2 = (struct ListNode*)malloc(sizeof(struct ListNode));
	m2->val = 3;

	struct ListNode* m3 = (struct ListNode*)malloc(sizeof(struct ListNode));
	m3->val = 4;

	n1->next = n2;
	n2->next = n3;
	n3->next = NULL;
	
	mergeTwoLists1(n1, m1);
	mergeTwoLists2(n1, m1);
	
	return 0;
}

请添加图片描述

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。