双指针:用两个变量动态存储两个节点,来方便我们进行操作。通常用在线性的数据结构中,解决链表问题。
步骤:
一般情况:指针的走位
特殊情况:边界条件
例题
一、反转链表
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
class Solution {
public ListNode reverseList(ListNode head) {
if(head==null || head.next== null)
return head;
ListNode p1=head;
ListNode p2=null;
while (p1 != null)
{
ListNode temp = p1.next;
p1.next = p2;
p2 = p1;
p1 = temp;
}
return p2;
}
}
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
if head == None or head.next == None:
return head
p1 = head
p2 = None
while p1 != None:
temp = p1.next
p1.next = p2
p2 = p1
p1 = temp
return p2
二、删除链表的倒数第K个节点
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode p1 = head;
//p1移动n位
while(n>0)
{
p1 = p1.next;
n--;
}
ListNode p2 = head;
if (p1 == null)
{
return p2.next;
}
while(p1.next != null)
{
p1=p1.next;
p2=p2.next;
}
p2.next = p2.next.next;
return head;
}
}
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
p1 = head
while n>0:
p1 = p1.next
n -= 1
p2 = head
if p1 == None:
return p2.next
while p1.next != None:
p1 = p1.next
p2 = p2.next
p2.next = p2.next.next
return head
任务
一、排序链表
给你链表的头结点 head
,请将其按 升序 排列并返回 排序后的链表
归并思想:
拆开排序后再合并。
class Solution:
##取出链表中间的数值
def getMid(self,head:Optional[ListNode]) -> Optional[ListNode]:
head = ListNode(0, head) ##决定了是否含有最后一个数字
slow = head
fast = head
while (fast != None and fast.next != None):
#slow走一步,fast走两步,待fast走到终点时,slow在中点
slow = slow.next
fast = fast.next.next
return slow
#对两个链表进行合并
def mergeTwoList(self,l1:Optional[ListNode], l2:Optional[ListNode]) -> Optional[ListNode]:
dump =ListNode()#设置一个空链表
last = dump
while (l1 != None and l2 != None):
#谁的值小,谁就被填入空链表中,不断遍历
if l1.val <= l2.val :
last.next = l1
l1 = l1.next
else:
last.next = l2
l2 = l2.next
last = last.next
if l1 != None :
last.next = l1
if l2 != None :
last.next = l2
return dump.next
def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if head == None:
return None
mid = self.getMid(head)
if mid.next == None:
return mid
headB = mid.next
mid.next = None
#将链表拆成一半,进行合并
return self.mergeTwoList(self.sortList(head), self.sortList(headB))
class Solution {
public ListNode sortList(ListNode head) {
if (head == null) {
return null;
}
ListNode mid = getMid(head);
if (mid.next == null) {
return mid;
}
ListNode headB = mid.next;
mid.next = null;
return mergeTwoList(sortList(head), sortList(headB));
}
public ListNode getMid(ListNode head) {
head = new ListNode(0, head);
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
public ListNode mergeTwoList(ListNode l1, ListNode l2) {
ListNode dump = new ListNode();
ListNode last = dump;
while (l1 != null && l2 != null) {
if (l1.val <= l2.val) {
last.next = l1;
l1 = l1.next;
} else {
last.next = l2;
l2 = l2.next;
}
last = last.next;
}
if (l1 != null) {
last.next = l1;
}
if (l2 != null) {
last.next = l2;
}
return dump.next;
}
}
二、环形链表
给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true 。 否则,返回 false 。
使用快慢指针,当指针相遇时,说明链表中存在环。
class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
slow = head
fast = head
while fast != None and fast.next != None:
slow = slow.next
fast = fast.next.next
if slow == fast:
return True
三、删除排序链表中的重复元素
class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
if not head or not head.next: return head
cur = head
while cur:
next = cur.next
while next:
if cur.val == next.val:
#cur 连接next.next
cur.next = next.next
next = next.next
cur = cur.next
return head