链表的简单应用

链表题的解题技巧

  1. 额外数据结构记录,哈希表
  2. 快慢指针

快慢指针的技巧

  • 【技巧】通过快慢指针得到链表的中间节点
    快指针一次走两步,慢指针一次走一步;
    a) 对于奇数个节点的链表,快慢指着从指着首节点的位置开始,快指针一次 走两步,慢指针一次走一步;当快指针走到最后一个节点的时候,满指针刚好指向正中间的一个节点
    b) 对于奇数个节点的链表,慢指针和快指针分别从首节点位置和第二个节点的位置出发,快指针一次走两步,慢指针一次走一步;当快指针走到最后一个节点的时候,满指针刚好指向正中间位置的前一个节点
    c) 注意当连链表的长度是1,2或者3的时候也要对;

快慢指针在链表中的经典例题

【例题1】反转链表1
【例题2】反转链表2
【例题3】回文链表

【例题4】
在这里插入图片描述

  • 解法1
    将链表里边的值放进数组,然后再数组里边快速排序;然后再遍历排序以后的数组,放进链表

再排序总结的文章里提到快速排序是没有稳定性的,然后再交换数字的时候,就导致数字的相对顺序已经变了;但是链表不会;再链表里边使用快速排序也可以保证稳定性

利用六个变量求解;分别记录小于区域大于区域和等于区域的头尾;相当于用三个辅助链表来完成任务;但是下边的代码只使用了六个变量,没有使用额外的空间,相比使用三个额外的

  • code
#include<vector>
#include<iostream>
#include<math.h>
#include<climits>
#include<set>
using namespace std;


struct ListNode {
	int val;
	ListNode* next;
	ListNode() : val(0), next(nullptr) {}
	ListNode(int x) : val(x), next(nullptr) {}
	ListNode(int x, ListNode* next) : val(x), next(next) {}
	
};

ListNode* get_res(ListNode* head,int piovt)
{
	ListNode* sH = new ListNode(0);
	ListNode* sT = new ListNode(0);
	ListNode* eH = new ListNode(0);
	ListNode* eT = new ListNode(0);
	ListNode* mH = new ListNode(0);
	ListNode* mT = new ListNode(0);

	ListNode* cur = head;
	while (cur)
	{
		if (cur->val < piovt)
		{
			if (sH == nullptr)
			{
				sH = cur;
				sT = cur;
			}
			else
			{
				sT->next = cur;
				sT = cur;
			}
		}
		else if (cur->val == piovt)
		{
			if (eH == nullptr)
			{
				eH = cur;
				eT = cur;
			}
			else
			{
				eT->next = cur;
				eT = cur;
			}
		}
		else
		{
			if (mH == nullptr)
			{
				mH = cur;
				mT = cur;
			}
			else
			{
				mT->next = cur;
				mT = cur;
			}
		}
	}
	if (sT) //如果有小于区域
	{
		sT->next = eH;
		eT = eT == nullptr ? sT : eT;//下一步谁去连接大于去区域的头,谁就是eT
	}
	if (eT != nullptr)//如果小于区域和等于区域没有全军覆没
		eT->next = mH;

	return sH != nullptr ? sH : (eH != nullptr ? eH : mH);

}

【例题5】
在这里插入图片描述

  • 解题思路1
    构建map,原始链表节点作为key,对应的value就是自身节点的属性value构建的新的节点;
    然后遍历原始节点,将原始节点的next和rand属性传递给自身的vlaue节点;
  • 解题思路1 code(使用哈希表)
#include<iostream>
#include<map>
using namespace std;

struct ListNode {
	int val;
	ListNode* next;
	ListNode* rand;
	ListNode() : val(0), next(nullptr) {}
	ListNode(int x) : val(x), next(nullptr) {}
	ListNode(int x, ListNode* next) : val(x), next(next) {}

};

ListNode* copy_list(ListNode* head)
{
	map<ListNode*, ListNode*> hashmap;
	ListNode* cur = head;
	while (cur)
	{
		hashmap[cur] = new ListNode(cur->val);
		cur = cur->next;
	}
	ListNode* cur = head;
	while (cur)
	{
		hashmap[cur]->next = cur->next;
		hashmap[cur]->rand = cur->rand;
	}
	return hashmap[head];
}
  • 解题思路2
    在这里插入图片描述
    -解题思路2code(不使用哈希表)
#include<iostream>
#include<map>
using namespace std;

struct ListNode {
	int val;
	ListNode* next;
	ListNode* rand;
	ListNode() : val(0), next(nullptr) {}
	ListNode(int x) : val(x), next(nullptr) {}
	ListNode(int x, ListNode* next) : val(x), next(next) {}

};

ListNode* copy_list(ListNode* head)
{
	ListNode* cur = head;
	//将copy的结点插入原始结点的后边
	//  |-------
	//  |      |
	//  1->1'->2->2'->3->3'->null
	//  |             |  
	//  |--------------
	while (cur)
	{
		ListNode* temp = cur->next;
		cur->next = new ListNode(cur->val);
		cur = cur->next;
		cur->next = temp;
		cur = cur->next;
	}
	//为copy的结点加上rand指针
	cur = head;
	while (cur)
	{
		cur->next->rand = cur->rand == nullptr ? nullptr : cur->rand->next;
		/*if (cur->rand == nullptr)
		{
			cur->next->rand = nullptr;
		}
		else
			cur->next->rand = cur->rand->next;*/
		cur = cur->next->next;
	}
	//更正原始结点和copy结点的next结点,分离两个链表
	ListNode*  res = head->next;
	cur = head;
	while (cur)
	{
		ListNode* next = cur->next->next;
		ListNode* copycur = cur->next;
		cur->next = next;
		copycur->next = next->next;
		cur = next;
	}
	return res;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星光技术人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值