Leetcode链表

Leetcode链表

一.闲聊

边学边刷的……慢慢写慢慢更

二.题目

1.移除链表元素


题干:

LkQ26J.png


思路:

  • 删除链表节点,就多了一个判断等值。
  • 由于是单向链表,所以要删除节点时要找到目标节点的上一个节点,如果是双向链表,指向要删除节点本身即可
  • 链表的头节点存在着被删除的风险,所以使用虚拟头节点来方便返回

代码:

public class ListNode{
int val;
ListNode next;
ListNode() {}
ListNode(int val) {this.val=val;}
ListNode(int val,ListNode next) {this.val=val;this.next=next;}
}
class Soulution{
public ListNode removeElements(ListNode head,int val){
//做个特判
if(head==null){
return head;
}
//以下两句可以用最后的构造器合并成一行。
ListNode dummy=new ListNode(0);
dummy.next=head;
ListNode cur=dummy;
while(cur.next!=null){
if(cur.next.val==val){
cur.next=cur.next.next
}else{
cur=cur.next;
}
}
return dummy.next;
}
}

2.设计链表


题干:

Lkcp1e.png


思路:

  • 一步步顺着实现各个接口即可,长个心眼就是addAtIndex这个功能可以在特殊情况如Head和Tail中进行调用,没必要在两个方法重新编写了。、

代码:

class MyLinkedList {
int size;
ListNode head;
public MyLinkedList() {
size=0;
head=new ListNode(0);
}
public int get(int index) {
if(index<0||index>=size){
return -1;
}
ListNode cur=head;
for(int i=0;i<=index;i++){
cur=cur.next;
}
return cur.val;
}
public void addAtHead(int val) {
addAtIndex(0,val);
}
public void addAtTail(int val) {
addAtIndex(size,val);
}
public void addAtIndex(int index, int val) {
if(index<0){
index=0;
}
if(index>size){
return;
}
size++;
ListNode listNode=new ListNode(val);
ListNode cur=head;
for(int i=0;i<index;i++){
cur=cur.next;
}
listNode.next=cur.next;
cur.next=listNode;
}
public void deleteAtIndex(int index) {
if(index>=size||index<0){
return;
}
size--;
ListNode cur=head;
for(int i=0;i<index;i++){
cur=cur.next;
}
cur.next=cur.next.next;
}
}
class ListNode{
int val;
ListNode next;
ListNode(){}
ListNode(int val){
this.val=val;
}
}

这道题用了虚拟头节点,也可以理解为哨兵,目的是为了保证链表始终处于非空的状态。 而正由于存在虚拟头节点,所以与传统的链表操作存在不同,但思想一致。比如查找节点的值时,如果不存在虚拟头节点,那么我们循环index次即可,现在要循环index+1次。

3.翻转链表


题干:反转一个单链表。 示例:示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL


思路:

  • 双指针法即可。一前一后配合

代码:

class Solution {
public ListNode reverseList(ListNode head) {
ListNode cur=head;
ListNode pre=null;
while (cur!=null){
//将下一个节点保存,否则就找不到下一个了
ListNode temp=cur.next;
cur.next=pre;
pre=cur;
cur=temp;
}
return pre;
}
}

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


题干:

Lkxsat.png


思路:

  • 双指针,一快一慢,快的先走n+1步,保证慢指针最后会指向要删除节点的前一个节点,之后执行普通的删除节点操作即可
  • 这题同样存在着删除头结点的情况,所以使用虚拟头节点方便处理

代码:

class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy=new ListNode(0);
dummy.next=head;
ListNode fast=dummy;
ListNode slow=dummy;
for(int i=0;i<=n;i++){
fast=fast.next;
}
while (fast!=null){
fast=fast.next;
slow=slow.next;
}
slow.next=slow.next.next;
return dummy.next;
}
}

5.链表相交


题干:

LASdHA.png


思路:

  • 首先遍历第一个链表,其中会产生重复的部分必定不是两链表的相交点,所以可以利用哈希集合去重,并记录下每个节点。之后遍历第二条链表的同时在哈希集合中查找是否存在交集,存在的第一个交集即是链表的交点,之后的所有点都是共同点。

代码:

public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
Set<ListNode> set=new HashSet<ListNode>();
while (headA!=null){
set.add(headA);
headA=headA.next;
}
while (headB!=null){
if(set.contains(headB)){
return headB;
}
headB=headB.next;
}
return null;
}
}

6.环形链表II


题干:

LApsaR.png


思路:

  • 与链表相交题目相似,一种解法是同样可以利用哈希集合判断,遍历链表,当出现当前节点的下一节点已经存在于哈希集合当中时,我们就返回当前节点下一节点即可(也可以是当前节点出现在哈希集合中后,返回当前节点)

代码:

public class Solution {
public ListNode detectCycle(ListNode head) {
Set<ListNode> set=new HashSet<ListNode>();
ListNode cur=head;
while (cur!=null){
if(set.contains(cur)){
return cur;
}else{
set.add(cur);
}
cur=cur.next;
}
return null;
}
}
posted @   Appletree24  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示