链表(二)
两个链表的交叉
合并两个排序的链表
链表插入排序
链表排序(O(n log n) )
删除链表中倒数第n个节点
回文链表
合并两个排序的链表
输入两个单调递增的链表,输出两个链表合成后的链表,合成后的链表满足单调不减规则。
public class Solution { // 非递归 public ListNode Merge2(ListNode list1,ListNode list2) { ListNode dummy = new ListNode(0); ListNode lastNode = dummy; while(list1!=null && list2!=null){ if(list1.val<list2.val){ lastNode.next = list1; list1 = list1.next; }else{ lastNode.next = list2; list2 = list2.next; } lastNode = lastNode.next; } if(list1!=null){ lastNode.next = list1; }else{ lastNode.next = list2; } return dummy.next; } //递归 public ListNode Merge(ListNode list1,ListNode list2) { if(list1==null) return list2; if(list2==null){ return list1; } ListNode mergeHead = null; if(list1.val < list2.val){ mergeHead = list1; mergeHead.next = Merge(list1.next, list2); }else{ mergeHead = list2; mergeHead.next = Merge(list1, list2.next); } return mergeHead; } }
两个链表的交叉
找到两个单链表最开始的交叉节点
public ListNode getIntersectionNode(ListNode headA, ListNode headB) { if(headA==null || headB==null) return null; if(headA==headB) return headA; int cnt1=0, cnt2=0; ListNode head = headA; while(head!=null){ cnt1++; head = head.next; } head = headB; while(head!=null){ cnt2++; head = head.next; } while(cnt1>cnt2){ headA = headA.next; cnt1--; } while(cnt1<cnt2){ headB = headB.next; cnt2--; } while(headA!=headB){ headA = headA.next; headB = headB.next; } return headA; }
链表插入排序
public ListNode insertionSortList(ListNode head) { ListNode dummy = new ListNode(0); while (head != null) { ListNode node = dummy; while (node.next != null && node.next.val < head.val) { node = node.next; } ListNode temp = head.next; head.next = node.next; //插入 node.next = head; head = temp; // 跳到下一个 } return dummy.next; }
链表排序(O(n log n) )
在 O(n log n) 时间复杂度和常数级的空间复杂度下给链表排序。
public ListNode sortList(ListNode head) { if (head == null || head.next == null) { return head; } ListNode slow = head, fast = head.next.next; while (fast != null && fast.next != null) { fast = fast.next.next; slow = slow.next; } ListNode p2 = sortList(slow.next); slow.next = null; ListNode p1 = sortList(head); return merge(p1, p2); } private ListNode merge(ListNode p1, ListNode p2) { ListNode p, dummy = new ListNode(0); p = dummy; while (p1 != null && p2 != null) { if (p1.val < p2.val) { p.next = p1; p1 = p1.next; } else { p.next = p2; p2 = p2.next; } p = p.next; } p.next = (p1==null?p2:p1); return dummy.next; }
删除链表中倒数第n个节点
给定一个链表,删除链表中倒数第n个节点,返回链表的头节点。
public ListNode removeNthFromEnd(ListNode head, int n) { ListNode n1 = head; ListNode n2 = head; ListNode dummy = new ListNode(0); dummy.next = n2; int i = 0; while(i<n){ n1 = n1.next; i++; } while(n1.next!=null){ n1 = n1.next; n2 = n2.next; } n2.next = n2.next.next; return dummy.next; }
返回链表中倒数第k个结点
public ListNode findKthToTail(ListNode head, int k) { if(head==null || k<=0) return null; ListNode right = head; ListNode left = head; for(int i=1; i<k; i++){ if(right.next!=null) right = right.next; else return null; } while(right.next!=null){ left = left.next; right = right.next; } return left; }
回文链表
public boolean isPalindrome(ListNode head) { if(head==null) return true; ListNode fast = head; ListNode slow = head; while(fast!=null && fast.next!=null){ fast = fast.next.next; slow = slow.next; } // when the length is odd if(fast!=null){ fast = fast.next; } // reverse the second half ListNode prev = null; while(slow!=null){ ListNode tmp = slow.next; slow.next = prev; prev = slow; slow = tmp; } slow = prev; while(slow!=null){ if(head.val != slow.val){ return false; } head = head.next; slow = slow.next; } return true; }