合并有序链表
// 21public static ListNode mergeTwoLists(ListNode list1, ListNode list2) {// 3. 递归跳出条件if(list1 == null){return list2;}if(list2 == null){return list1;}// 1. 比较大小,值小的放入resListNode res = list1.val < list2.val?list1:list2;// 2. 进行递归,res的下一个与list1、list2值较大的进行比较// list1、list2来回切换逐一比较各自的值res.next = mergeTwoLists2(res.next,list1.val >= list2.val?list1:list2);return res;}
删除链表中重复的元素
思路:记录上一个节点的元素,用来后续的比较,如果不相等,当前节点成为上一个节点
已经排过序的,逐一扫描,没有排序的可以借助存储(重点在重复上),如map、set等
// 83public ListNode deleteDuplicates(ListNode head) {if(head == null){return null;}ListNode pre = head;ListNode cur = head.next;while(cur != null){if(cur.val == pre.val){pre.next = cur.next;}else{pre = cur;}cur = cur.next;}return head;}// 203public ListNode removeElements(ListNode head, int val) {ListNode res = head;ListNode pre = head;while(head != null){if(head.val == val){pre.next = head.next;}else{pre = head;}head = head.next;}if(res != null && res.val == val){res = res.next;}return res;}// 面试题 02.01. 移除重复节点public ListNode removeDuplicateNodes(ListNode head) {Map map = new HashMap();ListNode pre = head;ListNode cur = head;while(cur != null){if(!map.containsKey(cur.val)){map.put(cur.val,cur);pre = cur;}else{pre.next = cur.next;}cur = cur.next;}return head;}
删除链表中的节点
思路:链表中的节点和值是两回事
// 237. 删除链表中的节点// 将儿子的值给了它,然后它的孙子变成它的儿子public void deleteNode(ListNode node) {node.val = node.next.val;node.next = node.next.next;}
链表的中间节点(快慢指针)
思路:快慢指针,快指针走完的时候,慢指针正好走到中间
// 876. 链表的中间结点public ListNode middleNode(ListNode head) {ListNode slow = head;ListNode fast = head;int k = 0;while(fast != null && fast.next != null){slow = slow.next;fast = fast.next.next;k++;}return slow;}
查找倒数第k个结点
思路:
带头结点的单链表,结点结构为(data,next),在不改变链表的前提下,设计一个尽可能高效的算法,查找出链表中倒数第k(k为正整数)个位置上的结点。
第一种方法是先循环一遍链表确定结点个数n,则倒数第k个结点就是就是正数的第n+1-k个,然后在遍历一次链表就可以找到指定结点了,但显然需要遍历两遍链表。
第二种方法可以使用两个指针,第一个指针先走k-1步,然后第二个指针开始走。当第一个指针移动到最后时,第二个指针正好指向倒数第k个结点,只需要遍历一遍链表,显然更高效。
