🌿3.反转链表(简单但重要)
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
题目链接:反转链表https://leetcode-cn.com/problems/reverse-linked-list/
非常经典的题目,面试常考,人人都得必会的题!!
方法1双指针迭代:通过两个指针cur和pre,一次一次局部反转,遍历一次后完成全部反转。
class Solution { public ListNode reverseList(ListNode head) { //cur在左 pre在右 ListNode pre=head; ListNode cur=null; while(pre!=null){ //先保存住pre的next ListNode a=pre.next; pre.next=cur; cur=pre; pre=a; } return cur; } }
方法2递归:这道题的递归比较抽象,需要大家自己动手演示一下流程才能想明白,但其实逻辑和双指针是一样的,建议还是掌握双指针方法即可。
class Solution { public ListNode reverseList(ListNode head) { //递归出口 if (head == null || head.next == null) { return head; } ListNode newHead = reverseList(head.next); head.next.next = head; head.next = null; return newHead; } }
🌿4.两两交换链表中的节点(中等)
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
题目链接:两两交换链表中的节点https://leetcode-cn.com/problems/swap-nodes-in-pairs/
这道题的思路和上面很像,都是通过指针的思想,一定要去画图,这道题不画图一定会被搞混乱的,看while循环内的代码就能感觉到,再次印证了,做链表题目一定要画图找出执行流程。
cur设为虚拟头结点,为了统一操作,大家一定要养成设置虚拟头结点的习惯。
class Solution { public ListNode swapPairs(ListNode head) { if(head==null) return head; //设置一个虚拟头结点 ListNode dummyHead=new ListNode(-1,head); ListNode cur=dummyHead; while(cur.next!=null&&cur.next.next!=null){ ListNode a=cur.next; ListNode b=cur.next.next.next; cur.next=cur.next.next; cur.next.next=a; cur.next.next.next=b; cur=cur.next.next; } return dummyHead.next; } }
方法二递归:
这里的递归我刚开始也没理解,但是发现一篇很好的关于递归的博客——递归教学
class Solution { public ListNode swapPairs(ListNode head) { //终止条件:链表只剩一个节点或者没节点了,没得交换了。返回的是已经处理好的链表 if(head == null || head.next == null){ return head; } //一共三个节点:head, next, swapPairs(next.next) //下面的任务便是交换这3个节点中的前两个节点 ListNode next = head.next; head.next = swapPairs(next.next); next.next = head; //根据第二步:返回给上一级的是当前已经完成交换后,即处理好了的链表部分 return next; } }
🌿5.删除链表倒数第N个节点(中等)
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
题目链接:删除链表倒数第N个节点https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/
同样是非常经典的题目,解法也有很多,最基础最重要的还是利用快慢双指针加虚拟头节点。大家一定要在反复练习,多看题解区的题解,化他人的知识为自己所用。
class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { //快慢指针方法 //定义虚拟头结点 ListNode dummyHead=new ListNode(-1,head); //定义快慢指针,慢指针负责找到待删除节点的前一个节点 ListNode show=dummyHead; ListNode fast=dummyHead; //让fast先走n+1格,当fast走完时刚好show指向倒数第n+1个 for(int i=1;i<=n+1;i++){ fast=fast.next; } while(fast!=null){ fast=fast.next; show=show.next; } //删除show指向的下一个节点 show.next=show.next.next; return dummyHead.next; } }
🌿6.链表相交(面试题)
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
题目链接:链表相交https://leetcode-cn.com/problems/intersection-of-two-linked-lists-lcci/
这道题在LeetCode被判断为简单题,但是却有一点难度,很多容易被人忽视的小细节,如判断相等时我们应该判断的是节点相等而不是节点的val相等。这里通过长度差,让长短不一的两条链表在末尾对齐的情况下,从同一长度开始遍历,如果有相等的时候直接返回即可,遍历完仍未找到返回null。