在数据结构的最高层抽象里,只有两种结构,数组和链表。这两种结构,是所有其他数据结构实现的基础。队列和栈,可以用链表和数组来实现。图,可以用邻接表和邻接矩阵来实现,其中,邻接表就是链表,邻接矩阵就是数组。树,用数组实现,可以实现堆,用链表实现,可以实现二叉树,AVL树等等。

所以,链表的操作是掌握数据结构最基础的能力。一切数据结构的操作,无非就是遍历+增删查改。由于每一种数据结构有不同的特性,比如,数组结构,不需要存储指针,而链表结构需要存储指针。数据结构的增删查改,就是在这些特性的基础之上来完成的。

关于链表面试算法的第一块,主要来学习链表这种数据结构,是如何来实现删除节点的。

常见的删除节点题目有:

  1. 删除链表中的节点_leetcode273
  2. 移除链表元素_leetcode203
  3. 删除链表的倒数第N个节点_leetcode19
  4. 删除排序链表中的重复元素_leetcode83
  5. 删除排序链表中的重复元素 II_leetcode82

1.删除链表中的节点

思路分析:

在链表中,删除一个节点node的常见方法是,
找到该节点的前驱节点,修改节点的next指针,使其指向node的下一个节点。

时间复杂度为O(1)的方法:
把将要删除的node节点的值,替换为它的后继节点,然后删除它之后的节点即可。
但是,这种方法需要保证,被删除的节点不是链表末尾。
若是末尾,则只能通过找到前序节点的方法来实现删除。

被删除节点不为尾结点情况下,代码演示如下:

class Solution {public void deleteNode(ListNode toBeDeleted) { toBeDeleted.val = toBeDeleted.next.val;toBeDeleted.next = toBeDeleted.next.next;}
}

被删除节点可能为尾结点情况下,代码演示如下:

public static ListNode deleteNode(ListNode head,ListNode toBeDeleted){if(head==null || toBedeleted == null){return head;}// 若被删除节点为尾结点,则遍历链表,找到其前驱节点if(toBeDeleted.next == null){ListNode curr = head;while(curr.next!=toBeDeleted){curr = curr.next;}curr.next = null;//直接删除为节点}else{toBeDeleted.value = toBeDeleted.next.value;// 待删除的结点的下一个指向原先待删除引号的下下个结点,即将待删除的下一个结点删除  toBeDeleted.next = toBeDeleted.next.next;}//return head;}


2.移除链表元素

思路:

方法:哑结点+双指针
步骤:设置前驱指针pre和工作指针cur来遍历数组,若发现目标值,则删除,否则,一起向前。

代码:

class Solution {public ListNode removeElements(ListNode head, int val) {ListNode dummy = new ListNode(-1);dummy.next = head;ListNode pre = dummy;ListNode cur = head;while(cur!=null){if(cur.val==val){pre.next = cur.next;cur = cur.next;}else{pre=cur;cur=cur.next;}}return dummy.next;       }
}


3.删除链表的倒数第N个节点

思路:

使用两个指针,首先,p1指向头结点,p2指向第n+1个节点。
然后,p1,p2两个指针同时向后移动。当p2指向尾节点时,p1指向的便是倒数第n+1个节点。
倒数第n+1个节点为倒数第n个节点的前驱。
难点:如何定位到第n个节点,这个需要特别注意。使用for循环定位比使用while循环定位更易理解。巧用哑结点,避免空指针等多种情况的讨论。  

不使用哑结点来进行运算时,代码如下:

public ListNode removeNthFromEnd(ListNode head, int n) {ListNode p=head;int len=0;while (p!=null){p=p.next;++len;}if(len<n)return null;if(len==n) return head.next;ListNode p1=head,p2=head;// p1指向第一个数,需要移动n步,才能指向第n+1个数,此时p1与p2的距离为n。for(int i=1;i<=n;i++){p1=p1.next;}while (p1.next!=null){p1=p1.next;p2=p2.next;}p2.next=p2.next.next;return head;  }

使用哑结点的方式代码如下:

class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {ListNode dummy = new ListNode(-1);dummy.next = head;ListNode p1 = dummy;// p1实际上为被删除节点的前驱节点,即倒数第n+1个节点。ListNode p2 = dummy;// p2移动n步,指向原链表中的第n个节点,此时p1与p2之间的距离为n.for(int i=1;i<=n;i++){p2 = p2.next;}// p1,p2同时向后移,当p2指向尾节点时,p1指向倒数第n+1个节点while(p2.next!=null){p1=p1.next;p2=p2.next;}p1.next = p1.next.next;return dummy.next;}
}


4. 删除排序链表中的重复元素

题目:

注意事项:

在链表题中,需要注意的是操作链表的结点指针,一定要做非空检查,避免报空指针异常。

思路:

因为输入的列表已排序,
因此我们可以通过将结点的值与它之后的结点进行比较来确定它是否为重复结点。
如果它是重复的,我们更改当前结点的 next 指针,以便它跳过下一个结点并直接指向下一个结点之后的结点。

代码如下:

class Solution {public ListNode deleteDuplicates(ListNode head) {ListNode cur = head;while(cur!=null && cur.next !=null){if(cur.val==cur.next.val){cur.next = cur.next.next;}else{cur = cur.next;}}return head;}
}


5. 删除排序链表中的重复元素 II

题目:

给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现的数字。

思路:

和上一题相比,需要在代码中实现去重操作。
哑结点+双指针法。
哑结点用于记录不重复数字的头,
p1指向不重复数字的最后一位,p2作为工作指针,向前扫描。
去重的判断条件(p2!=null && p2.next!=null && p2.val !=p2.next.val)

代码如下:

class Solution {public ListNode deleteDuplicates(ListNode head) {ListNode dumpy = new ListNode(-1);ListNode p1 = dumpy;ListNode p2 = head;while(p2!=null){if(p2!=null && p2.next!=null && p2.val == p2.next.val){// 若重复,则实现去重操作int temp = p2.val;while(p2!=null&&p2.val==temp){p2=p2.next;// 去重操作}}else{// 否则将不重复节点加入到新链表中。ListNode next = p2.next;p2.next = null; // p2和原来节点断开p1.next=p2;  // 将阉割后的p2节点加到p1上p1 = p2;p2 = next;}}return dumpy.next;}
}


总结

从上述的五道链表删除题可以看出,这种题目常见的技巧是使用哑结点+双指针来做,可以避免很多非空的判断,使得代码健壮且简洁。

链表排序c++代码_[链表面试算法](一) 链表的删除-相关题型总结(6题)相关推荐

  1. 链表python笔试题目_python经典面试算法题1.4:如何对链表进行重新排序

    本题目摘自<Python程序员面试算法宝典>,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中. 1.4 对链表按照如下要求重新排序 [微软笔试题] 难度系数: ...

  2. 语言zzuli链表遍历_趣味图解算法之链表

    阅读本文约需要10分钟,您可以先关注我们或收藏本文,避免下次无法找到. 之前我们通过趣味图解法为大家介绍了二分查找的算法,今天我们一起来学习日常工作中经常能用到的算法链表. 成哥就是通过这个算法解决了 ...

  3. 中希尔排序例题代码_十大经典排序算法最强总结

    排序算法属于经典基础算法基本功,笔试面试基本都会涉及和考察的,有原题也有变化,不过基础的几大排序算法还是得尽可能熟悉,能在思路熟悉的前提下手写出代码就更好了. ❝为了防止不提供原网址的转载,特加原文链 ...

  4. 中希尔排序例题代码_【数据结构与算法】这或许是东半球分析十大排序算法最好的一篇文章...

    码农有道 历史文章目录(请戳我) 关于码农有道(请戳我) 前言 本文全长 14237 字,配有 70 张图片和动画,和你一起一步步看懂排序算法的运行过程. 预计阅读时间 47 分钟,强烈建议先收藏然后 ...

  5. 中希尔排序例题代码_超全面分析十大排序算法

    点击上方"零一视界",选择"星标"公众号 资源干货,第一时间送达 作者 | 不该相遇在秋天 责编 | 程序员小吴 前言 本文全长 14237 字,配有 70 张 ...

  6. java 单链表是否有环_数据结构与算法随笔之链表-链表是否有环(二)

    上一篇文章我们分析了下链表之反转单向链表,这篇文章我们来分析下另外一个关于链表的经典题目. 判断链表是否有环(在leetcode上的题目地址:环形链表) 题目描述 给定一个链表,判断链表中是否有环 解 ...

  7. 【C语言】单向链表排序、合并、逆序、分离(链表的头节点不储存数据)

    一.排序 编写程序,在第1题(第1题:编写程序,建立2个带头结点单链表,输入若干整数将正整数插入第1个单链表,将负整数插入第2个单链表,插入前和插入后单链表保持递增或相等次序,显示2个单链表,最后销毁 ...

  8. (关于单链表的真题)已知一个带有表头结点的单链表...请设计一个尽可能高效的算法,查找链表中倒数第k个位置的结点。

    真题描述 已知一个带有表头结点的单链表,结点结构为 data next 假设该链表只给出了头指针head.在不改变链表的前提下,请设计一个尽可能高效的算法,查找链表中倒数第k个位置上的结点. 若查找成 ...

  9. java编写排序的代码_在Java 8之前,您编写了几行代码来对对象集合进行排序?...

    java编写排序的代码 在Java 8之前,您编写了几行代码来对对象集合进行排序? Java 8您需要多少个? 您可以在Java 8中用一行完成. 让我们看看下面的Employee类. public ...

最新文章

  1. 好久没写了,重装了系统重新配置的Live Writer,看看效果:
  2. 信息系统项目管理师:第9章:项目人力资源管理-章节重点
  3. 【C++进阶】 遵循TDD原则,实现平面向量类(Vec2D)
  4. HTML pre元素
  5. [论文笔记]Convolutional Neural Networks for Sentence Classification
  6. 基于Quartz.Net的任务管理平台开发(3) —— 任务管理平台
  7. Wannafly 每日一题 2016-12-26 KAOS 字典树
  8. how to be successful with salesforce
  9. OpenCV-特征提取与检测(02、Shi-Tomasi角点检测)
  10. Unity3D渲染系列之SkyBox天空盒
  11. 华为回应出售手机业务传闻:假消息;微软将ChatGPT整合到更多工具中:不用写代码就能开发应用;苹果更新Mac产品线|极客头条
  12. 工厂制造业ai人工智能应用_人工智能与金融服务业转型的未来
  13. 分库分表和 NewSQL 到底怎么选?
  14. 码流 /码率 / 比特率
  15. python画图库哪个好_python画图库
  16. 超强的学习能力是怎样练就的~
  17. Microsoft SQL Server 图书管理数据库的建立
  18. 第一章 管理与管理学 第一节 笔记2018
  19. proteus 02 555定时器脉冲电路
  20. [OC]浙江理工大学OJ部分题解

热门文章

  1. numcpp速度对比_PHP和C++性能对比.pdf
  2. windows聚焦图片为什么不更新了_为什么年轻明星都不愿意接周星驰的戏? 林更新道出了事情的真相|周星驰|林更新|喜剧之王|演员...
  3. matlab imhist灰度直方图
  4. 隐马尔可夫模型 HMM 原理及实现
  5. LPCTSTR和CString的关系
  6. JAVA程序员面试题集合
  7. mysql语句表名大小写敏感_Mysql 表名大小写敏感
  8. Flutter快速构建集美观与⾼性能于⼀体的APP
  9. 实战|全程分析js到getshell
  10. oracle 10g客户端连接11g,生产环境oracle10g升级至11g准备工作