剑指Offer-链表问题
单链表
题目描述–jz3
输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
输入
{67,0,24,58}
输出
[58,24,0,67]
题目分析
使用Stack存储数据,pop()输出
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> res=new ArrayList<Integer>();
Stack<Integer> temp=new Stack<Integer>();
ListNode cur=listNode;
int count=0;
while(cur!=null){
temp.push(cur.val);
cur=cur.next;
count++;
}
for(int i=0;i<count;i++){
res.add(temp.pop());
}
return res;
}
题目描述–jz15
输入一个链表,反转链表后,输出新链表的表头。
输入
{67,0,24,58}
输出
[58,24,0,67]
题目分析
使用两个指针
temp存储后继节点
pre暂时存储反转链表的节点–输出的反转链表
第一句:存储下一次循环的节点
第二句:构建反转链表开始,第一个节点为null
第三句:cur节点已经与null相连,将cur存为反转节点的预备下一节点
第四句:跳入下一循环的准备,移动后续操作的节点。
public ListNode ReverseList(ListNode head) {
ListNode cur=head;
ListNode pre=null;
while(cur!=null){
ListNode temp = cur.next;
cur.next=pre;
pre=cur;
cur=temp;
}
return pre;
}
题目描述–jz14
输入一个链表,输出该链表中倒数第k个结点。
如果该链表长度小于k,请返回空。
输入
{1,2,3,4,5},1
输出
{5}
题目分析
倒数第k个结点
使用两个指针
反向测量
题目描述–jz36
输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
题目分析
考虑构建两个节点指针 A , B 分别指向两链表头节点 headA , headB ,做如下操作:
指针 A 先遍历完链表 headA ,再开始遍历链表 headB ,当走到 node 时,共走步数为:
a + (b - c)
a+(b−c)
指针 B 先遍历完链表 headB ,再开始遍历链表 headA ,当走到 node 时,共走步数为:
b + (a - c)
b+(a−c)
如下式所示,此时指针 A , B 重合,并有两种情况:
a + (b - c) = b + (a - c)
a+(b−c)=b+(a−c)
若两链表 有 公共尾部 (即 c > 0c>0 ) :指针 A , B 同时指向「第一个公共节点」node 。
若两链表 无 公共尾部 (即 c = 0c=0 ) :指针 A , B 同时指向 nullnull 。
因此返回 A 即可。
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode A = headA, B = headB;
while (A != B) {
A = A != null ? A.next : headB;
B = B != null ? B.next : headA;
}
return A;
}
}