关于链表的相关操作
1、寻找链表的中点
// 找到链表的中点(快慢指针) public ListNode getMidNode(ListNode head) { ListNode slow = head; ListNode fast = head; while (fast.next != null && fast.next.next != null) { slow = slow.next; fast = fast.next.next; } return slow; }
2、翻转链表
// 翻转链表 public ListNode reverse(ListNode head) { ListNode prev = null; ListNode curr = head; while(curr != null) { ListNode node = curr.next; curr.next = prev; prev = curr; curr = node; } return prev; }
3、合并链表
// 合并链表 public void merge(ListNode l1, ListNode l2) { ListNode l1_tmp; ListNode l2_tmp; while (l1 != null && l2 != null) { l1_tmp = l1.next; l2_tmp = l2.next; l1.next = l2; l1 = l1_tmp; l2.next = l1; l2 = l2_tmp; } }
综合例子143-重排链表
class Solution { public void reorderList(ListNode head) { if (head == null || head.next == null) return ; // 找到链表的中点 ListNode node = getMidNode(head); ListNode head1 = node.next; node.next = null; // 将左右两部分断开 // 翻转链表 head1 = reverse(head1); // 合并 merge(head, head1); } // 找到链表的中点(快慢指针) public ListNode getMidNode(ListNode head) { ListNode slow = head; ListNode fast = head; while (fast.next != null && fast.next.next != null) { slow = slow.next; fast = fast.next.next; } return slow; } // 翻转链表 public ListNode reverse(ListNode head) { ListNode prev = null; ListNode curr = head; while(curr != null) { ListNode node = curr.next; curr.next = prev; prev = curr; curr = node; } return prev; } // 合并链表 public void merge(ListNode l1, ListNode l2) { ListNode l1_tmp; ListNode l2_tmp; while (l1 != null && l2 != null) { l1_tmp = l1.next; l2_tmp = l2.next; l1.next = l2; l1 = l1_tmp; l2.next = l1; l2 = l2_tmp; } } }
k个一组反转链表
/** * 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 reverseKGroup(ListNode head, int k) { if (head == null || head.next == null) return head; ListNode dummy = new ListNode(-1, head); ListNode prev = dummy; while (head != null) { ListNode tail = prev; // tail往后移动 找到长度为k的子链 // 查看剩余部分长度是否>=k for (int i = 0; i < k; i++) { tail = tail.next; if (tail == null) { // 长度不足k 直接反转 return dummy.next; } } // 找到要分离的位置tail后,保存分离后的下一个位置,以便能装回原链表 ListNode next = tail.next; ListNode[] reverseSet = reverse(head, tail); head = reverseSet[0]; tail = reverseSet[1]; // 把子链重新装回原链表中 prev.next = head; tail.next = next; prev = tail; head = tail.next; } return dummy.next; } // 翻转链表,返回一个链表的首部和尾部 public ListNode[] reverse(ListNode head, ListNode tail) { ListNode prev = tail.next; ListNode curr = head; while (prev != tail) { ListNode next = curr.next; curr.next = prev; prev = curr; curr = next; } return new ListNode[]{tail, head}; } }
// 判断链表是否有环,以及环的入口在哪里
/** * 空间优化O(n) * 快慢指针可以用来判断是否有环 * 因为L_fast = 2L_slow * 出发点到相遇点的距离等于相遇点到环路的进入点 */ public class Solution { public ListNode detectCycle(ListNode head) { if (head == null || head.next == null) return null; ListNode dummy = new ListNode(-1); dummy.next = head; // 快慢指针的起始点 ListNode slow = head; ListNode fast = head.next; while(slow != fast) { // 如果无环 if (fast == null || fast.next == null) return null; slow = slow.next; fast = fast.next.next; }
// 相遇问题 ListNode ans = dummy; while (ans != slow) { ans = ans.next; slow = slow.next; } return ans; } }
作者:Ryanjie
出处:http://www.cnblogs.com/ryanjan/
本文版权归作者和博客园所有,欢迎转载。转载请在留言板处留言给我,且在文章标明原文链接,谢谢!
如果您觉得本篇博文对您有所收获,觉得我还算用心,请点击右下角的 [推荐],谢谢!