单链表专题---暴力算法美学(1)(有视频演示)

1.1 移除链表元素

题目要求:给你一个链表的头节点head 和一个整数val,请你删除链表中所有满足Node.val == val 的节点,并返回新的头节点。

思路一:遍历链表,遇到val就删除,pcur指向val的下一个节点,最后只剩下没有val的链表。

思路二:创建新的链表,头节点用newHead,尾插newTail,pcur来遍历原链表,当pcur!=val,就把数值拿下来,尾插到newTail中,最后新的链表中没有val。

cs 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode ListNode;
struct ListNode* removeElements(struct ListNode* head, int val)//指向头节点的指针,要删除的数值
{
	//创建一个新链表
	ListNode* newHead, *newTail;
	newHead = newTail = NULL;

	//遍历原链表
	ListNode* pcur = head;
	while (pcur)//pcur!=NULL
	{
		//找值不为val的节点,尾插到新链表中
		if (pcur->val != val)
		{
		//当链表为空时
			if (newHead == NULL)
			{
				newHead = newTail = pcur;
			}
			else//链表不为空
			{
				newTail->next = pcur;//将pcur的值插入newTail的下一个节点
				newTail = newTail->next;//最后让newTail走向下一个节点
			}
			pcur = pcur->next;
		}
	}
    if (newTail)//newTail!=NULL
		newTail->next = NULL;
		return newHead;
}

1.2 反转链表

思路一:创建新的链表,将原链表中的节点拿过来头插。

思路二:创建三个指针,完成链表的翻转。

cs 复制代码
//反转链表
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode ListNode;
struct ListNode* reverseList(struct ListNode* head) {
    //判断链表是否为空
    if(head==NULL)
    return head;
    ListNode* n1,*n2,*n3;//创建三个指针实现反转
    //介绍三个指针分别在什么地方
    n1 = NULL, n2 = head, n3 = n2->next;
    while(n2)//判断结束节点,n2!=NULL
    {
        n2->next=n1;
        n1=n2;
        n2=n3;
        if(n3)
            n3=n3->next;
    }
    return n1;//n1是链表新的头节点
}

反转链表算法题思路

1.3 链表的中间节点

思路一:遍历原链表,count计节点数,直接返回(count / 2)节点的next节点

思路二:快慢指针

cs 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode ListNode;
struct ListNode* middleNode(struct ListNode* head) {
    //创建两个指针
    ListNode* fast,* slow;
    fast=head;
    slow=head;//两个创建的指针都指向head头节点
    while(fast && fast->next)//偶数链表遍历结束条件fast=NULL,奇数链表遍历结束条件fast->next=NULL
    {
        slow=slow->next;
        fast=fast->next->next;
    }
    return slow;
}

问题:while(fast->next && fast)可以交换位置吗?

不可以!若链表有偶数个节点的情况下,fast最后一次会直接走到空,fast->next会执行报错!

链表的中间节点的思路二:快慢指针

1.3.1拓展提升:删除链表的中间节点

cs 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode ListNode;
struct ListNode* deleteMiddle(struct ListNode* head) {
    struct ListNode* slow, *fast, *dummy, *tmp;
    dummy=(struct ListNode*)malloc(sizeof( ListNode));
    dummy->next=head;
    slow = fast = dummy;
    while(fast->next != NULL && fast->next->next != NULL) {
        slow = slow->next;
        fast = fast->next->next;
    }
    tmp = slow->next;
    slow->next = tmp->next;
    free(tmp);
    return dummy->next;
}

问题:为什么要额外申请一个空间放置dummy,dummy->next=head,头节点head本身就是存在的,为什么要有一个dummy来指向head?

答: dummy(虚拟头节点)使用来简化边界情况处理的"工具人"。如果链表只有一个节点,这个唯一节点就是"中间节点",需要被删除,如果没有dummy,直接删除head,结果会返回NULL,而dummy->next永远指向实际链表的头节点,不管头节点有没有被删除,最后返回的都是dummy->next,不用单独处理头节点被删除导致head无效的情况。

删除链表的中间元素解题思路

相关推荐
Sapphire~15 小时前
重学JS-004 --- JavaScript算法与数据结构(四)JavaScript 表单验证
前端·javascript·数据结构·算法
剪一朵云爱着15 小时前
PAT 1088 Rational Arithmetic
算法·pat考试
勤劳的进取家15 小时前
论文阅读:GOAT: GO to Any Thing
论文阅读·人工智能·算法·语言模型·自然语言处理
luofeiju15 小时前
直线拟合方法全景解析:最小二乘、正交回归与 RANSAC
人工智能·线性代数·算法·机器学习·数据挖掘·回归
卡尔曼的BD SLAMer16 小时前
北斗导航 | RAIM算法改进方案及性能对比分析报告
算法·raim·接收机自主完好性·mhss·多假设、
ShineWinsu17 小时前
对于牛客网—语言学习篇—编程初学者入门训练—复合类型:BC136 KiKi判断上三角矩阵及BC139 矩阵交换题目的解析
c语言·c++·学习·算法·矩阵·数组·牛客网
luoganttcc19 小时前
Fast-LIVO2算法与其他激光雷达-惯性-视觉里程计算法相比有何优势?
算法
mu_guang_1 天前
计算机算术8-浮点加法
算法·cpu·计算机体系结构
Jayden_Ruan1 天前
C++计算正方形矩阵对角线和
数据结构·c++·算法
李白同学1 天前
C++:list容器--模拟实现(下篇)
开发语言·数据结构·c++·windows·算法·list