链表的定义:
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
-
输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
分析: 本题利用递归调用实现,还可以利用栈先入后出分特性完成,也可以利用
Collections.reverse(list)
方法直接将list反转,这里不再赘述。import java.util.ArrayList; public class Solution { ArrayList<Integer> array = new ArrayList<Integer>(); public ArrayList<Integer> printListFromTailToHead(ListNode listNode) { if (listNode != null) { this.printListFromTailToHead(listNode.next); array.add(listNode.val); } return array; } }
-
输入一个链表,输出该链表中倒数第k个结点。
分析: 本题利用两个指针,实现一个长度为k的测量尺,当第一个指针到达链表结尾时,第二个指针正好位于倒数第k个节点。
public class Solution { public ListNode FindKthToTail(ListNode head,int k) { ListNode h = head; ListNode t = head; int i = 0; for (; h != null; i++) { if (i >= k) { t = t.next; } h = h.next; } return i >= k ? t : null; } }
注意: 当链表总节点数小于k时,返回null。
-
输入一个链表,反转链表后,输出新链表的表头。
分析: 本体利用两个指针pre 指向当前节点的前一个节点,next指向当前节点的下一个节点,实现链表的反转。
方法一非递归方法
实现步骤如下:
步骤1、head→next1→next2
步骤2、next = head.next;
实现next→next1→next2,next用来保存head之后的节点
步骤3、head.next = pre;
实现head→pre,完成链表的反转
步骤4、最后head和pre分别向后移动一个节点重复上述过程,直到head == null;
public class Solution { public ListNode ReverseList(ListNode head) { ListNode pre = null; ListNode next = null; if (head == null) { return null; } while (head != null) { next = head.next; head.next = pre; pre = head; head = next; } return pre; } }
方法二递归方法
首先利用递归到达最后一个节点,将其赋给pre,pre一直不变,然后执行
head.next.next = head head.next = null;
这两句语句,此时head为倒数第二个节点,
head.next.next = head
实现将倒数第一个节点指向倒数第二个节点,然后第二个节点指向空。下一次递归实现将倒数第二个节点指向倒数三个节点直到递归结束,这个过程中pre一直是指向原链表的最后一个节点,最后返回pre就实现了整个链表的反转。疑问 : 为什么链表在这个过程中没有断裂?
在上一次递归中,前一个节点的next == null, 下一次递归中的节点为什么还能使上一个节点指向本次递归中的节点,不理解。public class Solution { public ListNode ReverseList(ListNode head) { if (head == null || head.next == null) { return head; } ListNode pre = ReverseList(head.next); head.next.next = head; head.next = null; return pre; } }
-
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
分析: 利用两个指针,一个头指针,头指针确定后不再移动,current指针随循环移动,最后返回头指针。从头开始分别比较两个链表中元素的值,取出较小的元素放在新链表中,然后后移,重复。public class Solution { public ListNode Merge(ListNode list1,ListNode list2) { if (list1 == null) { return list2; } if (list2 == null) { return list1; } ListNode mergeHead = null; ListNode current = null; while ((list1 != null) && (list2 != null)) { if (list1.val <= list2.val) { if (mergeHead == null) { mergeHead = list1; current = list1; } else { current.next = list1; current = current.next; } list1 = list1.next; } else { if (mergeHead == null) { mergeHead = list2; current = list2; } else { current.next = list2; current = current.next; } list2 = list2.next; } } if (list1 == null) { current.next = list2; } if (list2 == null) { current.next = list1; } return mergeHead; } }
-
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)**
分析: 分三步来实现首先,复制链表,将复制后的链表元素依次放在原链表元素的后面,不考虑特殊指针。
实现代码如下:RandomListNode currentNode = pHead; while (currentNode != null) { RandomListNode cloneNode = new RandomListNode(currentNode.label); RandomListNode nextNode = currentNode.next; currentNode.next = cloneNode; cloneNode.next = nextNode; currentNode = nextNode; }
然后,复制特殊指针。
实现代码如下:currentNode = pHead; while (currentNode != null) { if (currentNode.random != null){ currentNode.next.random = currentNode.random.next; } currentNode = currentNode.next.next; }
最后,将两个链表分开。
实现代码如下:currentNode = pHead; RandomListNode cloneHead = pHead.next; while (currentNode != null) { RandomListNode cloneNode = currentNode.next; currentNode.next = cloneNode.next; if (cloneNode.next != null){ cloneNode.next = cloneNode.next.next; } currentNode = currentNode.next; }
整体代码如下:
public class Solution { public RandomListNode Clone(RandomListNode pHead){ if (pHead == null) { return null; } RandomListNode currentNode = pHead; while (currentNode != null) { RandomListNode cloneNode = new RandomListNode(currentNode.label); RandomListNode nextNode = currentNode.next; currentNode.next = cloneNode; cloneNode.next = nextNode; currentNode = nextNode; } currentNode = pHead; while (currentNode != null) { if (currentNode.random != null){ currentNode.next.random = currentNode.random.next; } currentNode = currentNode.next.next; } currentNode = pHead; RandomListNode cloneHead = pHead.next; while (currentNode != null) { RandomListNode cloneNode = currentNode.next; currentNode.next = cloneNode.next; if (cloneNode.next != null){ cloneNode.next = cloneNode.next.next; } currentNode = currentNode.next; } return cloneHead; } }