🔥题目
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
输入:1 → 3 → 2 → 4
输出: [4, 2, 3, 1]
☘️解析
立即想到3种思路
1)递归打印
2)借助辅助栈迭代打印
3)扫描两次,第一次扫描得到链表长度。第一次扫描将元素落位到数组
🧊代码
class Solution1 {
public int[] reversePrint(ListNode head) {
// 递归打印
printList(head);
int[] res = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
res[i] = list.get(i);
}
return res;
}
private List<Integer> list = new ArrayList<>();
private void printList(ListNode node) {
if (node == null) {
return;
}
printList(node.next);
list.add(node.val);
}
}
class Solution2 {
public int[] reversePrint(ListNode head) {
// 借助辅助栈迭代打印
Deque<Integer> stack = new LinkedList<>();
while (head != null) {
stack.push(head.val);
head = head.next;
}
int[] res = new int[stack.size()];
for (int i = 0; i < res.length; i++) {
res[i] = stack.pop();
}
return res;
}
}
class Solution3 {
public int[] reversePrint(ListNode head) {
// 扫描两次,第一次扫描得到链表长度。第一次扫描将元素落位到数组
ListNode node = head;
// 第一次
int len = 0;
while (node != null) {
node = node.next;
len++;
}
// 第二次
int[] res = new int[len];
int index = len - 1;
node = head;
while (node != null) {
res[index--] = node.val;
node = node.next;
}
return res;
}
}
🌸补充
三种思路的是时间复杂度都是O(n)。
但是对比效率,两次扫描效率最高,使用辅助栈效率次之,递归效率最低。
🔥题目
输入一个链表,输出该链表中倒数第k个节点。
为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
输入:1 → 2 → 3 → 4 → 5,k=2
输出:4
☘️解析
解法一:两次遍历
第一次遍历得到链表长度len,第二次遍历得到正数第(len-k+1)个节点,即为倒数第k个节点。
解法二:快慢指针
先让快指针走k步,再让快慢指针同步一起走,快指针走到头(null)时,慢指针即为倒数第k个节点。
🧊代码
解法一:两次遍历
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
int len = 0;
ListNode cur = head;
while (cur != null) {
cur = cur.next;
len++;
}
cur = head;
while (len - k > 0) {
cur = cur.next;
len--;
}
return cur;
}
}
解法二:快慢指针
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode slow = head;
ListNode fast = head;
while (k > 0) {
fast = fast.next;
k--;
}
while (fast != null) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
}
🌸补充
两次遍历是非常朴素的思路,快慢指针是非常经典的思路。推荐后者。