链表问题

1|0203. 移除链表元素

203. 移除链表元素

  1. 链表删除操作: 使用dummyHead, 遍历cur.next值是否等于val, 再执行删除操作, 使用while (cur.next != null) 循环
  2. 递归方法: 递归可以方便的进行重建链表, 重建过程中删除等于val就满足了条件。
//增加虚拟头节点: 使得头节点与其他节点处理方式一致化 class Solution { public ListNode removeElements(ListNode head, int val) { ListNode dummyHead = new ListNode(0, head); //开始遍历操作: 链表中,定义cur节点进行遍历操作, pre,next等可以作为前后节点 ListNode cur = dummyHead; while (cur.next != null) { if (cur.next.val == val) { cur.next = cur.next.next; } else { cur = cur.next; } } return dummyHead.next; } } //直接处理: 头节点与其他节点分开处理 class Solution2 { public ListNode removeElements(ListNode head, int val) { //在链表循环中: p!=null 往往作为中止条件 while (head != null && head.val == val) { head = head.next; } ListNode cur = head; if (cur == null) { return null; } while (cur.next != null) { if (cur.next.val == val) { cur.next = cur.next.next; } else { cur = cur.next; } } return head; } } //递归: 链表具有递归性质, 可以使用递归处理,递归的代码顺序: 递归出口-> 递归逻辑-> 递归返回, 递归的编码顺序: 递归逻辑-> 递归返回-> 递归出口 class Solution3 { public ListNode removeElements(ListNode head, int val) { //递归出口 if (head == null) { return null; } //递归逻辑 head.next = removeElements(head.next, val); //递归返回 return head.val == val ? head.next : head; } }

2|0设计链表

707. 设计链表

class ListNode { int val; ListNode next; ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } class MyLinkedList { ListNode dummyHead;//虚拟头节点 int size;//链表大小 /** * Initialize your data structure here. */ public MyLinkedList() { this.dummyHead = new ListNode(0); this.size = 0; } /** * Get the value of the index-th node in the linked list. If the index is invalid, return -1. */ public int get(int index) { if (index < 0 || index >= size) { return -1; } ListNode cur = this.dummyHead.next; while (index > 0) { cur = cur.next; index--; } return cur.val; } /** * Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. */ public void addAtHead(int val) { addAtIndex(0, val); } /** * Append a node of value val to the last element of the linked list. */ public void addAtTail(int val) { addAtIndex(size, val); } /** * Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. */ public void addAtIndex(int index, int val) { if (index < 0 || index > size) { return; } ListNode newNode = new ListNode(val); ListNode cur = this.dummyHead; while (index > 0) { cur = cur.next; index--; } newNode.next = cur.next; cur.next = newNode; size++; } /** * Delete the index-th node in the linked list, if the index is valid. */ public void deleteAtIndex(int index) { if (index < 0 || index >= size) { return; } ListNode cur = this.dummyHead; while (index > 0) { cur = cur.next; index--; } cur.next = cur.next.next; size--; } } /* Your MyLinkedList object will be instantiated and called as such: MyLinkedList obj = new MyLinkedList(); int param_1 = obj.get(index); obj.addAtHead(val); obj.addAtTail(val); obj.addAtIndex(index,val); obj.deleteAtIndex(index); */

3|0206.反转链表

206.反转链表
使用dummyHead,需要pre 和 cur同时移动

class Solution { public ListNode reverseList(ListNode head) { ListNode pre = null; ListNode cur = head; while (cur != null) { ListNode temp = cur.next; cur.next = pre; pre = cur; cur = temp; } return pre; } }

4|0两两交换链表

两两交换链表

  1. 使用dummyHead, 分三步控制指向变化
class Solution { public ListNode swapPairs(ListNode head) { ListNode dummyHead = new ListNode(0, head); ListNode cur = dummyHead; while (cur.next != null && cur.next.next != null) { ListNode temp = cur.next; ListNode temp2 = cur.next.next.next; cur.next = cur.next.next; cur.next.next = temp; cur.next.next.next = temp2; cur = cur.next.next; } return dummyHead.next; } }

5|0删除倒数第N个节点

删除倒数第N个节点

  1. 快慢指针间隔N进行同步移动, 快指针移动到null时, 删除慢指针位置的下一个位置.
// 快慢指针保持距离n同步移动: 0-> 1-> 2-> 3->null class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { //0<n<=size ListNode dummyHead = new ListNode(0, head); ListNode slowIndex = dummyHead, fastIndex = dummyHead; //fastIndex向前走n步: 因为向前走n步slowIndex位置为要删除的位置,没有上一步的记录-> 改为:向前走n+1步即n>0改为n>=0 while (n >= 0) { fastIndex = fastIndex.next; n--; } //保持距离同步移动到fastIndex到末尾 while (fastIndex != null) { fastIndex = fastIndex.next; slowIndex = slowIndex.next; } //slowIndex的下一个位置就是要删除的位置 slowIndex.next = slowIndex.next.next; return dummyHead.next; } }

6|0链表相交

链表相交

// set解法: 遍历一个链表元素存入set中, 遍历另一个链表,元素逐个和set中对比, 相等则返回, 最后返回null public class Solution { public ListNode getIntersectionNode(ListNode headA, ListNode headB) { HashSet<ListNode> hashSet = new HashSet<>(); for (ListNode cur = headA; cur != null; cur = cur.next) { hashSet.add(cur); } for (ListNode cur = headB; cur != null; cur = cur.next) { if (hashSet.contains(cur)) { return cur; } } return null; } }

7|0环形链表

环形链表

  1. 判断是否有环: HashSet存储已遍历的节点, 后序遇到后则证明存在环, 并且是入口点
  2. 快慢指针, 快指针步长2, 慢指针步长1, 最后会在环内相交, 寻找入口的: 指针一从头遍历. 指针2从相交出遍历, 最后在入口点相交。
public class Solution { public ListNode detectCycle(ListNode head) { HashSet<ListNode> hashSet = new HashSet<>(); ListNode cur = head; while (cur != null) { hashSet.add(cur); if (hashSet.contains(cur.next)) { return cur.next; } else { cur = cur.next; } } return null; } }

__EOF__

本文作者Rocky
本文链接https://www.cnblogs.com/nrocky/p/15893694.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   -Rocky-  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示