leetcode题解:链表


🚝1. 删除链表中的节点

在这里插入图片描述
题目解析 观察到题目给定的参数只有一个节点,且该节点非末尾,可以把该节点的下一节点直接连到下下个节点上,再将值改为下一个节点的值。

代码

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public void deleteNode(ListNode node) {
        ListNode nextNode=node.next;
        node.next=nextNode.next;
        node.val=nextNode.val;
    }
}

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

在这里插入图片描述
题目解析 这题解题的关键是首先 在链表头再定义一个呀哑节点 然后可以观察题目得到我们需要计算链表长度L,然后删除倒数第n个其实是删除从列表开头数起的第 (L-n+1)个结点。可以从哑节点遍历到,待删除的节点前一个节点,将该节点的下一个节点定义为待删除节点的下一个节点。 哑节点的目的就是为啥删除第一个节点。
代码

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy=new ListNode(0);
        dummy.next=head;
        ListNode first=head;
        int length=0;
        while(first!=null){
            length++;
            first=first.next;
        }
        length=length-n;
        first=dummy;
        for(int i=0;i<length;i++){
            first=first.next;
        }
        first.next=first.next.next;
        return dummy.next;
    }
}

🚝3.反转链表

在这里插入图片描述
方法一
定义两个指针:b和a ;a为null,b为链表第一项
每次让 b 的 next 指向 a ,实现一次局部反转
局部反转完成之后, a 和 b 同时往前移动一个位置,a 移动到 b 的位置,b 则移动到一下项,循环上述过程,直至 a 到达链表尾部

双指针代码

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        if(head==null){return null;}
          ListNode a=null;
          ListNode b=head;
        while(b!=null){
          ListNode c=b.next;
          b.next=a;
            a=b;
            b=c;
        }
        return a;
    }
}

方法二 递归找到链表的最后一个结点,该结点是反转后的头结点 ,每次函数在return前,让当前结点的下一个结点的 next 指针指向当前节点。让当前结点的next指针指向null ,从而实现从链表尾部开始的局部反转。
递归函数全部出栈后,链表反转完成。

代码

class Solution {
    public ListNode reverseList(ListNode head) {
         if(head==null||head.next==null){return head;}
         ListNode ret=reverseList(head.next);
         head.next.next=head;
         head.next=null;
         return ret;
    }
}

🚝4.合并两个有序链表

在这里插入图片描述
题目解析 因为两个链表有序,所以可以定义同时遍历两个链表,将比较小的节点拿出来连接成新的链表

代码

/**
 * Definition for singly-linked list.
 * 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 Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        //定义一个新链表
      ListNode result=new ListNode(0);
        //flag记录新链表头节点
        ListNode flag=result;
        while(l1!=null&&l2!=null){
            if(l1.val<=l2.val){result.next=l1;result=result.next;l1=l1.next;}
            else if(l1.val>l2.val){result.next=l2;result=result.next;l2=l2.next;}
        }
        if(l1==null){while(l2!=null){result.next=l2;result=result.next;l2=l2.next;}}
        if(l2==null){while(l1!=null){result.next=l1;result=result.next;l1=l1.next;}}
        return flag.next;
    }
    
}

🚝5.回文链表

在这里插入图片描述
题目解析 直接将链表取出得到数组,双指针判断是否回文数组。
❗值得注意的是在比较int类型的数据时,使用equals而不是==,因为超过-128~128的int型数据需要new而不是从常量池取,所以地址不同。

代码

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isPalindrome(ListNode head) {
        List<Integer> array=new ArrayList<Integer>();
        while(head!=null){
            array.add(head.val);
            head=head.next;
        }
        int i=0;
        int j=array.size()-1;
        while(i<j){
            if(!array.get(i).equals(array.get(j))){return false;}
            i++;j--;
        }
        return true;
    }
}

🚝6.环形链表

在这里插入图片描述
题目解析 遍历链表,并将遍历过的节点放入set集合,当set出现重复节点说明链表有环
代码

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
       Set<ListNode> set=new HashSet<ListNode>();
        while(head!=null){
            if(set.contains(head)){return true;}
            set.add(head);
            head=head.next;
        }
        return false;
    }
}

🚝7.反转链表 II

在这里插入图片描述
题目解析 首先找到需要反转部分的头部left与尾部right,头部前置节点preleft,头部的下一个节点nextleft用于反转。
使用双指针将这一部分链表反转,然后将头部前置节点preleft的next设置为反转后的头部,反转后的尾部的next设置为原来尾部后置节点(双指针反转后可得到)
代码

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseBetween(ListNode head, int m, int n) {
        boolean flag=false;
        if(head==null){return null;}
        if(n==1){return head;}
        if(m==1){flag=true;}
        ListNode left=head;
        ListNode right=head;
        ListNode preleft=null;
        int time=n-m;
        while(m-1>0){
            preleft=left;
            left=left.next;
            m--;
        }
        ListNode begin=left;
        ListNode nextleft=left.next;

        while(n-1>0){
            right=right.next;
            n--;
        }
        if(flag){head=right;}
        
    
        for(int i=0;i<time;i++){
           ListNode temp=nextleft.next;
           nextleft.next=left;
           left=nextleft;
           nextleft=temp;
        } 
       begin.next=nextleft;
       if(preleft!=null)preleft.next=left;
        

    return head;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值