当前位置:   article > 正文

双指针技巧,链表

双指针技巧,链表

双指针链表

虚拟头节点+双指针,都要用虚拟1头节点

合并两个有序链表

设置双指针,都指向虚拟头节点

ListNode list1 代表的是头节点

  1. class Solution {
  2. public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
  3. ListNode dummy=new ListNode(-1);
  4. ListNode p=dummy;
  5. ListNode p1=list1;
  6. ListNode p2=list2;
  7. while(p1!=null&&p2!=null){
  8. if(p1.val<p2.val){
  9. p.next=p1;
  10. p1=p1.next;
  11. }else{
  12. p.next=p2;
  13. p2=p2.next;
  14. }
  15. p=p.next;
  16. }
  17. if(p1!=null){
  18. p.next=p1;
  19. }
  20. if(p2!=null){
  21. p.next=p2;
  22. }
  23. return dummy.next;
  24. }
  25. }

单链表的分解(两个小链表可能会成环,要处理

具体来说,我们可以把原链表分成两个小链表,一个链表中的元素大小都小于 x,另一个链表中的元素都大于等于 x,最后再把这两条链表接到一起,就得到了题目想要的结果。

  1. /**
  2. * Definition for singly-linked list.
  3. * public class ListNode {
  4. * int val;
  5. * ListNode next;
  6. * ListNode() {}
  7. * ListNode(int val) { this.val = val; }
  8. * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
  9. * }
  10. */
  11. class Solution {
  12. public ListNode partition(ListNode head, int x) {
  13. ListNode dummy1=new ListNode(-1);//记录小于x
  14. ListNode dummy2=new ListNode(-1);
  15. ListNode p=head,p1=dummy1,p2=dummy2;
  16. while(p!=null){
  17. if(p.val<x){
  18. p1.next=p;
  19. p1=p1.next;
  20. }else{
  21. p2.next=p;
  22. p2=p2.next;
  23. }
  24. ListNode temp=p.next;//断开p的next,否则会成环
  25. p.next=null;
  26. p=temp;
  27. }
  28. p1.next=dummy2.next;
  29. return dummy1.next;
  30. }
  31. }

合并k个升序链表(用优先队列实现最小堆

每次弹出最小的结点值,给新链表。

弹出一个,要再存入一个

  1. class Solution {
  2. public ListNode mergeKLists(ListNode[] lists) {
  3. ListNode dummy=new ListNode(-1);
  4. ListNode p=dummy;
  5. PriorityQueue<ListNode> pq=new PriorityQueue<>((a,b)->(a.val-b.val));//创建最小堆
  6. for(ListNode head:lists){
  7. if(head!=null) pq.add(head);
  8. }
  9. while(!pq.isEmpty()){
  10. ListNode node=pq.poll();//弹出一个最小的
  11. if(node.next!=null){
  12. pq.add(node.next);//存入下一个结点
  13. }
  14. p.next=node;
  15. p=p.next;
  16. }
  17. return dummy.next;
  18. }
  19. }

删除链表倒数第n个结点

定义两个指针,一个在左一个在右边,距离为n,右指针走n次即可。走到最后一个结点则停止,因为删除结点要知道要删除结点的前一个结点。

  1. class Solution {
  2. public ListNode removeNthFromEnd(ListNode head, int n) {
  3. ListNode dummy=new ListNode(-1,head);
  4. ListNode left=dummy;
  5. ListNode right=dummy;
  6. while(n-->0){
  7. right=right.next;
  8. }
  9. while(right.next!=null){
  10. left=left.next;
  11. right=right.next;
  12. }
  13. left.next=left.next.next;
  14. return dummy.next;
  15. }
  16. }

链表的中间结点

定义快慢指针,走两步和走一步。返回slow.next

  1. class Solution {
  2. public ListNode middleNode(ListNode head) {
  3. ListNode dummy=new ListNode(-1,head);
  4. ListNode slow=dummy,fast=dummy;
  5. while(fast.next!=null&&fast.next.next!=null){
  6. slow=slow.next;
  7. fast=fast.next.next;
  8. }
  9. return slow.next;
  10. }
  11. }

环形链表

快慢指针判断链表是否为环形,在相遇点时,slow重置到head。快慢指针同时开始走1步直到相遇则是环。

  1. public class Solution {
  2. public ListNode detectCycle(ListNode head) {
  3. if(head==null||head.next==null) return null;//这里条件是或
  4. ListNode slow=head;
  5. ListNode fast=head;
  6. ListNode p=head;
  7. while(fast!=null&&fast.next!=null){
  8. slow=slow.next;
  9. fast=fast.next.next;
  10. if(slow==fast) break;
  11. }
  12. if(slow!=fast){
  13. return null;
  14. }
  15. slow=head;
  16. while(slow!=fast){
  17. slow=slow.next;
  18. fast=fast.next;
  19. }
  20. return slow;
  21. }
  22. }

相交链表

遍历完A遍历B,遍历完B遍历A,之后会相交

  1. public class Solution {
  2. public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
  3. ListNode p1=headA;
  4. ListNode p2=headB;
  5. while(p1!=p2){
  6. p1=p1.next;
  7. p2=p2.next;
  8. if(p1==null&&p2==null) return null;
  9. if(p1==null) p1=headB;
  10. if(p2==null) p2=headA;
  11. }
  12. return p1;
  13. }
  14. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/956934
推荐阅读
相关标签
  

闽ICP备14008679号