目录
快慢指针
在初始化设置指向链表头结点时,设置两个指针,快慢指针,前进时快指针fast在前,慢指针slow在后,巧妙解决链表中的一些问题。
判断链表中是否有环
每次快指针多走一步,假设环长为x,当快指针多走x步时会与慢指针相遇
快指针是每次走两步,慢指针每次走一步
而不是快指针一开始指向head的下一个 慢指针指向head 两个一起走
https://leetcode.cn/problems/linked-list-cycle/
public class Solution {
public boolean hasCycle(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while(fast!=null && fast.next!=null){
fast = fast.next.next;
slow = slow.next;
if(fast==slow) return true;
}
return false;
}
}
https://leetcode.cn/problems/happy-number/
class Solution {
public int getSum(int n){
int sum = 0;
while(n>0){
sum += (n%10)*(n%10);
n/=10;
}
return sum;
}
public boolean isHappy(int n) {
int fast = getSum(n);
int slow = n;
while(fast!=1){
if(fast==slow) return false;
fast = getSum(getSum(fast));
slow = getSum(slow);
}
return true;
}
}
已知链表中含有环,返回这个环的起始位置
https://leetcode.cn/problems/linked-list-cycle-ii/
假设慢指针和快指针相遇,也就是在起始位置,此时slow走了k步,那么快的由于每次走两步,所以一共走了2k步 也就是环的长度是k
相遇点不一定就在环的起始位置(最简单的两个点的就能论证)
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode fast = head;
ListNode slow = head;
int k = 0;
while(fast!=null && fast.next!=null){
k++;
fast = fast.next.next;
slow = slow.next;
if(fast==slow){
fast = head;
while(fast!=slow){
fast = fast.next;
slow = slow.next;
}
return slow;
}
}
return null;
}
}
寻找链表的中点
https://leetcode.cn/problems/middle-of-the-linked-list/submissions/
class Solution {
public ListNode middleNode(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while(fast!=null){
fast = fast.next;
if(fast==null) return slow;
slow = slow.next;
fast = fast.next;
}
return slow;
}
}
寻找链表的倒数第 k 个元素
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode fast = head;
ListNode slow = head;
while(k-->0){
fast = fast.next;
}
while(fast!=null){
fast = fast.next;
slow = slow.next;
}
return slow;
}
}
剑指 Offer II 026. 重排链表
https://leetcode.cn/problems/LGjMqU/
/**
* 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 void reorderList(ListNode head) {
if(head.next==null)
return ;
ListNode slow = head;
ListNode fast = head;
ListNode tt = slow;
while(fast!=null && fast.next!=null){
tt = slow;
fast = fast.next.next;
slow = slow.next;
}
tt.next = null;
ListNode pre = slow;
ListNode prepre = null;
while(slow!=null){
pre = slow;
slow = slow.next;
pre.next = prepre;
prepre = pre;
}
ListNode head2 = pre;
//head head2
while(head!=null){
ListNode t = head.next;
head.next = head2;
head2 = head2.next;
if(t!=null)
head.next.next = t;
head = t;
}
}
}
删除链表的倒数第 N 个结点
https://leetcode.cn/problems/remove-nth-node-from-end-of-list/
/**
* 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 low = head;
ListNode fast = head;
for(int i=0; i<n; i++){
fast = fast.next;
}
if(fast==null){
head = head.next;
}
else{
while(fast.next!=null){
fast = fast.next;
low = low.next;
}
low.next = low.next.next;
}
return head;
}
}
234. 回文链表
https://leetcode.cn/problems/palindrome-linked-list/
/**
* 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 boolean isPalindrome(ListNode head){
//空或者只有一个:true
if(head==null || head.next==null)
return true;
ListNode fast = head;
ListNode slow = head;
ListNode pre = head;
ListNode prepre = null;
//边快慢指针边走 边翻转
while(fast!=null && fast.next!=null){ //走到最后一个的位置前 否则不能next.next
pre = slow;//注意要pre先走到slow位置 这样slow前移后 之前走过的全改变方向
fast = fast.next.next;
slow = slow.next;
pre.next = prepre;
prepre = pre;
// pre = slow; //放在这里 pre的next是原链表的后半部分 会断开
}
//奇数个 否则fast每次都是next next 偶数个最后必为null
if(fast!=null){
slow = slow.next;
}
while(slow!=null && pre!=null){
if(slow.val!=pre.val)
return false;
slow = slow.next;
pre = pre.next;
}
return true;
}
}