leetcode - 链表
链表专题训练。
1、反转链表
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public ListNode reverseList(ListNode head) { if(head == null) return null; if(head.next == null) return head; ListNode temp = head.next; head.next = null; ListNode next = null; while(temp != null) { next = temp.next; temp.next = head; head = temp; temp = next; } return head; } }
2、反转链表2
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
public ListNode reverseBetween(ListNode head, int m, int n) { if(head == null) return null; if(head.next == null) return head; ListNode start = head; ListNode front = null; int count = 1; while(count != m) { if(start != null) { front = start; start = start.next; } count++; } ListNode temp = start.next; ListNode need = start; start.next = null; ListNode next; while(temp != null && count != n) { next = temp.next; temp.next = start; if(front != null) { front.next = temp; } start = temp; temp = next; count++; } if(temp != null) { need.next = temp; } if(m == 1) head = start; return head; }
3、对链表进行插入排序
对链表进行插入排序。
插入排序的动画演示如上。从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示)。
每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的链表中。
插入排序算法:
插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。重复直到所有输入数据插入完为止。
示例 1:
输入: 4->2->1->3
输出: 1->2->3->4
class Solution { public ListNode insertionSortList(ListNode head) { if(head == null) return head; if(head.next == null) return head; ListNode current = head.next; head.next = null; ListNode next = current.next; if(current.val > head.val) { head.next = current; current.next = null; current = next; next = next.next; } while (current != null || next != null) { ListNode temp = findTargetPosition(current, head); head = temp == null ? head : temp; current = next; if(current != null) { next = next.next; } } return head; } public ListNode findTargetPosition(ListNode current, ListNode head) { ListNode node = head; ListNode front = head; while (node != null) { if (node == head && node.val >= current.val) { current.next = node; node = current; break; } else if (node != head && node.val >= current.val) { current.next = front.next; front.next = current; node = head; break; } else { front = node; node = node.next; if(node == null) { front.next = current; current.next = null; } } } return node; } }
4、合并两个有序链表
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
public class MergeTwoLists { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { if(l1 == null && l2 == null) return null; ListNode a = l1; ListNode b = l2; ListNode temp = new ListNode(0); ListNode root = temp; while(a != null || b!= null) { int x = b == null ? Integer.MAX_VALUE : b.val; int y = a == null ? Integer.MAX_VALUE : a.val; if(y > x) { temp.next = b; b = b.next; temp = temp.next; } else { temp.next = a; a = a.next; temp = temp.next; } } return root.next; } }
5、合并K个排序链表
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
public class MergeKLists { public ListNode mergeKLists(ListNode[] lists) { ArrayList<ListNode> arrayList = new ArrayList<>(); ListNode root = new ListNode(0); ListNode temp = root; for (ListNode elem: lists) { while(elem != null) { arrayList.add(elem); elem = elem.next; } } Collections.sort(arrayList, new Comparator<ListNode>() { @Override public int compare(ListNode o1, ListNode o2) { return o1.val - o2.val; } }); for (ListNode elem: arrayList) { temp.next = elem; temp = temp.next; } return root.next; } }
6、K个一组翻转链表
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
> 示例 :
> 给定这个链表:1->2->3->4->5
> 当 k = 2 时,应当返回: 2->1->4->3->5
> 当 k = 3 时,应当返回: 3->2->1->4->5
> 说明 :
> 你的算法只能使用常数的额外空间。
> 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
public class ReverseKGroup { public ListNode reverseKGroup(ListNode head, int k) { if(head == null) return null; int t = k; int length = getLength(head); int count = length / k; int mod = length % k; ListNode temp = head; ListNode next = head.next; ListNode start = new ListNode(0); ListNode root = start; while (count !=0) { if(t!=0) { temp.next = start.next; start.next = temp; temp = next; if (temp != null) next = next.next; t--; } else { t = k; count--; start = head; head = temp; } } if(mod != 0) { while (temp != null){ start.next = temp; temp = temp.next; start = start.next; } } return root.next; } public int getLength(ListNode head) { int length = 0; ListNode temp = head; while (temp != null) { length++; temp = temp.next; } return length; } }