本期我们就主要单链表利用双指针解决经典问题的技巧进行分析讲解
表解体经典思路解法——双指针的应用
本期我们讲解的链表面试题使用的技巧都是一样,主要通过利用两个指针来解决问题。上期我们讲解的链表环的问题其中快慢指针方法也用到了这种技巧
经典面试题:链表相交的问题
给定两个单链表,判断是否有相交,相交的话找到最开始的交点
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) {
return null;
}
int lenA = 1;
int lenB = 1;
ListNode tempA = headA;
ListNode tempB = headB;
while (tempA.next != null) {
lenA++;
tempA = tempA.next;
}
while (tempB.next != null) {
lenB++;
tempB = tempB.next;
}
if (!tempA.equals(tempB)) {
return null;
}
int reduseCount = lenA - lenB;
tempA = headA;
tempB = headB;
if (reduseCount > 0) {
for (int i = 0; i < reduseCount; i++) {
tempA = tempA.next;
}
} else {
reduseCount = Math.abs(reduseCount);
for (int i = 0; i < reduseCount; i++) {
tempB = tempB.next;
}
}
while (tempB != null && tempA != null) {
if (tempB.equals(tempA)) {
return tempB;
}
tempA = tempA.next;
tempB = tempB.next;
}
return null;
}
思路:主要利用双指针的技巧,先将比较长的那个链表截取后部分,然后使得两个链表长度相同,此时从起点同时向后走会同时到达终点,其中必定同时到达第一个相交处。两个指针分别向后走,然后分别比较,如果指向相同节点,那么说明找到了相交处,然后返回。
经典面试题:链表删除倒数某个节点
删除链表的倒数第K个节点
**思考:**看到题目首先我们想到的是一定是遍历两便链表,第一遍首先知道链表的长度,然后算出何时可以从头到倒数第K个节点,然后直接在第二遍遍历时候取出来。但是有没有一种方法只遍历一遍就可以得到结果呢?这里我们使用双指针方式来解决。我们直接上代码:
public ListNode removekthFromEnd(ListNode head, int k) {
if (head == null) {
return null;
}
ListNode first = head;
ListNode sec = head;
for (int i = 0; i < k; i++) {
first = first.next;
}
while (first != null && first.next != null) {
first = first.next;
sec = sec.next;
}
sec.next = sec.next.next;
return head;
}
思路:这是一个双指针法思路来解决的典型例题。首先让指针first指向头节点,然后让其向后移动k步,然后指针sec指向头结点和first同时以相同的速度向后移动。first的next指针为NULL同时sec就指向了要删除节点的前一个节点,接着让sec指向的next指针指向要删除节点的下一个节点就可以将对应的节点删除。
经典面试题:查找链表中的中间节点
我们直接上代码:
public ListNode SearchMid(ListNode head) {
ListNode p = this.head, q = this.head;
while (p != null && p.next != null && p.next.next != null) {
p = p.next.next;
q = q.next;
}
return q;
}
思路:这个题目和上期我们解决的含有环的链表类似,用到了快慢指针,让快指针的速度是慢指针的速度的两倍,那么当快指针到达了终点,那么慢指针就正好到达中间的位置。
|