小浩算法-java题解(链表篇)


原文链接
https://www.geekxh.com/0.0.%E5%AD%A6%E4%B9%A0%E9%A1%BB%E7%9F%A5/01.html
这里是把这个大佬的题解用java写一下做个记录

链表篇

第19题:删除链表倒数第N个节点

给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:

给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:

给定的 n 保证是有效的。
进阶:

你能尝试使用一趟扫描实现吗?

解题思路:用一个哨兵节点res定位,然后用两个指针pre和cur,指向这个哨兵节点,其中cur是要删除的节点,用head进行遍历,当head距离cur有n-1时,cur开始移动,pre始终在cur的前一个,直到head指向null,结束后pre.next=pre.next.next就删除了cur,最后返回res.next。

/**
 * 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 res=new ListNode(0);//哨兵节点
         res.next=head;
         ListNode pre=res;
         ListNode cur=res;
         int i=1; //距离是n-1,所以从1开始
         while(head!=null)
         {
             if(i>=n)
             {
                 pre=cur;
                 cur=cur.next;
             }
             head=head.next;
             i++;
         }
         pre.next=pre.next.next;
         return res.next;
    }
}

哨兵节点的妙处:
在这里插入图片描述

第21题:合并两个有序链表

将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:

输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4

解题思路:
方法一: 递归

class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
          if(l1==null && l2==null) return null;
          if(l1==null) return l2;
          if(l2==null) return l1;
          if(l1.val<l2.val)
          {
              l1.next=mergeTwoLists(l1.next,l2);//下一个是其中那个小的,下面类推
              return l1;
          }else
          {
              l2.next=mergeTwoLists(l1,l2.next);
              return l2;
          }
    }
}

方法二: 使用哨兵节点res,pre用来遍历新的链表,然后再在两个里进行比较,取其中小的那个,最后返回哨兵节点res.next。官方解里有图。

class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
          if(l1==null && l2==null) return null;
          if(l1==null) return l2;
          if(l2==null) return l1;
          ListNode pre=new ListNode(0);
          ListNode res=pre;
          while(l1!=null && l2!=null)
          {
              if(l1.val<l2.val)
              {
                  pre.next=l1;
                  l1=l1.next;
              }else
              {
                  pre.next=l2;
                  l2=l2.next;
              }
              pre=pre.next;
          }
          if(l1!=null) pre.next=l1;
          if(l2!=null) pre.next=l2;
          return res.next;
    }
}

第141题:环形链表

给定一个链表,判断链表中是否有环。为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。
示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

解题思路:快慢指针,快指针走两步,慢指针走一步,如果相遇说明就有环。

public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head == null || head.next== null) return false;
        ListNode slow=head;
        ListNode fast=head.next;
        while(fast!=slow)
        {
            if(fast==null || fast.next==null) return false;
            fast=fast.next.next;
            slow=slow.next;
        }
        return true;
    }
}

第2题:两数相加

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

解题思路: 构建一个新的链表,这个链表的每一个值都是给的两个链表值的和,然后考虑进位。用哨兵节点指向我们的新链表。建议看大佬的图解,很直观。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
      ListNode list=new ListNode(0);
      ListNode res=list;
      int tmp=0;
      while(l1!=null || l2 != null || tmp!=0 )//这个是判断是不是结束,tmp是判断进位后
      //的那个是不是结束,比如[5] [5]按照这样是0,1满足条件,而如果没有tmp就变成了0。
      {
          if(l1!=null)
          {
              tmp+=l1.val;
              l1=l1.next;
          }
          if(l2!= null)
          {
              tmp+=l2.val;
              l2=l2.next;
          }
          list.next=new ListNode(tmp%10);//填入后面的值
          tmp/=10;//判断是不是进位了,如果没有那么这个就是0。
          list=list.next;//新链表后移
      }
      return res.next;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值