24. 两两交换链表中的节点
- 自我尝试
- 代码
/** * 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 swapPairs(ListNode head) { // 因为head可能会变,保留dummyHead更加方便操作 ListNode dummyHead = new ListNode(-1, head); ListNode pre = dummyHead; ListNode cur = dummyHead.next; ListNode tmp; // cur为奇数位node.当cur.next为null说明不需要换。不为null,按部就班换 while(cur!=null && cur.next!=null){ // 记录下第三个 tmp = cur.next.next; // 串上头 pre.next = cur.next; // 第二个指向第一个,调换! cur.next.next = cur; // 将第三个地址留回来 cur.next = tmp; pre = cur; cur = cur.next; } return dummyHead.next; } }
- 代码
- 范例题解
- 代码
- 递归法
class Solution { public ListNode swapPairs(ListNode head) { // base case 退出提交 if(head == null || head.next == null) return head; // 获取当前节点的下一个节点 ListNode next = head.next; // 进行递归 ListNode newNode = swapPairs(next.next); // 这里进行交换 next.next = head; head.next = newNode; return next; } }
- 递归法
- 代码
19.删除链表的倒数第N个节点
- 自我尝试
- 代码
/** * 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 removeNthFromEnd(ListNode head, int n) { if (head==null){ return head; } int size = 0; ListNode dummyHead = new ListNode(-1,head); ListNode pre=dummyHead; // count the element while(pre.next!=null){ pre = pre.next; size++; } int removIndx= size-n; pre = dummyHead; for(int i=0;i<removIndx;i++){ pre = pre.next; } pre.next=pre.next.next; return dummyHead.next; } }
- 收获
- 思路:遍历完一遍,确认了总数,然后确定要删除的index
- 代码
- 范例题解
- 代码
/** * 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 removeNthFromEnd(ListNode head, int n) { //双指针方法 ListNode dummyHead = new ListNode(-1,head); ListNode fast = dummyHead; ListNode slow = dummyHead; for(int i=0;i<n;i++){ fast = fast.next; } while(fast.next!=null){ slow=slow.next; fast=fast.next; } slow.next = slow.next.next; return dummyHead.next; } }
- 收获
- 思路:双指针法——快慢指针。移除倒数n个,首先让fast指针先偏移n个index,即n+1个node。随后,fast与slow一起遍历直到fast.next为空(到底了)。此时的slow指的就是要移除node的前一个,可以直接轻松移除。
- 注意第一个for循环里面的条件i<n,不可以等于。
- 代码
面试题 02.07. 链表相交
- 自我尝试
- 代码-暴力法
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public ListNode getIntersectionNode(ListNode headA, ListNode headB) { //暴力法: ListNode a=headA; while(a!=null){ ListNode b=headB; while(b!=null){ if(a==b){ return a; } b=b.next; } a=a.next; } return null; } }
- 收获
- 思路:O(N*M)将每个node都比较一下。
- 代码-暴力法
- 范例题解
- 代码-迭代法
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public ListNode getIntersectionNode(ListNode headA, ListNode headB) { ListNode a =headA; ListNode b =headB; int sizeA =0; int sizeB =0; while(a!=null){ sizeA++; a=a.next; } while(b!=null){ sizeB++; b=b.next; } int gap=0; ListNode longList; ListNode shortList; if(sizeA>sizeB){ longList = headA; shortList = headB; gap = sizeA-sizeB; }else{ longList = headB; shortList = headA; gap = sizeB-sizeA; } for(int i=0;i<gap;i++){ longList = longList.next; } while(longList!=null){ if(longList==shortList){ return longList; } longList=longList.next; shortList=shortList.next; } return null; } }
- 收获
- 代码-迭代法
142.环形链表II
- 自我尝试
- 代码
- HashMap
/** * Definition for singly-linked list. * class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ import java.util.HashMap; import java.util.Map; public class Solution { public ListNode detectCycle(ListNode head) { Map<ListNode, Integer> dic = new HashMap<>(); while(head!=null){ if(dic.containsKey(head)){ return head; } dic.put(head,1); head=head.next; } return null; } }
- ArrayList
/** * Definition for singly-linked list. * class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ import java.util.ArrayList; public class Solution { public ListNode detectCycle(ListNode head) { ArrayList<ListNode> nlst = new ArrayList<>(); while(head!=null){ if(!nlst.contains(head)){ nlst.add(head); head=head.next; }else{ return head; } } return null; } }
- HashMap
- 代码
- 范例题解
- 代码
/** * Definition for singly-linked list. * class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ import java.util.ArrayList; public class Solution { public ListNode detectCycle(ListNode head) { if (head==null){ return null; } ListNode fast = head; ListNode slow = head; while(fast.next!=null && fast.next.next!=null){ fast = fast.next.next; slow = slow.next; if(fast==slow){ ListNode tmp = head; while(tmp!=slow){ tmp= tmp.next; slow = slow.next; } return slow; } } return null; } }
- 收获
- 思路:这个方法很数学。1.通过快慢指针确定是否是环 2. 通过推导确定相遇位置,进而推出入口点。
- 代码