24. Swap Nodes in Pairs
Given a linked list, swap every two adjacent nodes and return its head. You must solve the problem without modifying the values in the list's nodes (i.e., only nodes themselves may be changed.) Input: head = [1,2,3,4] Output: [2,1,4,3]
思路:
元素互换关键就是修改对应node.next的指向。
每次互换两个Nodes(比如node1和node2),其实涉及三个Node,node1, node2, node2.next(的地址)。为了方便指代第一个node,再加一个dummy_head。那么总共就是要记住四个Node:dummy_head,node1,node2,node2.next(的地址)。node1和node2.next都先用temp1和temp记住。第一次赋值,直接用dummy_head.next = dummy_head.next.next也就使用完了node2的地址。接下来再用temp和temp1记住的地址赋值来实现互换即可。
同时,这也可以写成【迭代法】。但是迭代法就不设置dummy_head了,每组node1和node2互换后,node1才是继续接下一组的node,node1.next也才是每轮迭代的output。具体实现看代码。
Solution:
class Solution(object):
def swapPairs(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
dummy_head = ListNode(next=head)
current = dummy_head
while current.next and current.next.next: # cur 1 2 3 4 -> cur 2 1 3 4
temp = current.next # temp = ori1
temp1 = current.next.next.next # temp2 = ori3
current.next = current.next.next # cur ori2 ori2 ori3 ori4
temp.next = temp1 # ori1.next = ori3
current.next.next = temp #cur new2 ori1
current = current.next.next
return dummy_head.next
# 迭代法
class Solution(object):
def swapPairs(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if head is None or head.next is None:
return head
# pre and cur are two nodes to swap
pre = head
cur = head.next
next = head.next.next
cur.next = pre # swap cur and pre
pre.next = self.swapPairs(next) #将以next为head 的后续链表两两交换
return cur
Time complexity: O(n)
Space complexity: O(1)
19. Remove Nth Node From End of List
Given thehead
of a linked list, remove thenth
node from the end of the list and return its head. Input: head = [1,2,3,4,5], n = 2 Output: [1,2,3,5]
Solution:
思路:brute force: 先看整个链表的总长,减去n,即为要被移除的元素的index。但更简单的方法是用快慢指针,这样不用遍历两次链表。那就是让快指针比慢指针快n个元素,然后快指针再和慢指针一块出发知道快指针指向最后一个元素,那时慢指针指向的元素的下一个就是要被移除的。
注意!这里写for循环时应该是让快指针先走n步,所以是range(n+1)不是range(n),算不清楚的时候举个具体的例子。具体见代码里的comment。
注意!本题中写while的时候,不要写fast.next。具体如下。
while fast: # 注意!不是fast.next!!!! 如果是fast.next的话,在最后一次进入while时,fast=fast.next=None.对Nonetype.next是没有意义的会报错!!!
slow = slow.next
fast = fast.next
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution(object):
def removeNthFromEnd(self, head, n):
"""
:type head: ListNode
:type n: int
:rtype: ListNode
"""
dummy_head = ListNode(0, next=head) # Example: dummy_head 1th 2th 3th(3th from end) 4th(2th from end) 5th(1th from end)
fast,slow = dummy_head,dummy_head
for i in range(n+1): # if n = 2 # 是n还是n+1,举个简单的例子推导一下。
fast = fast.next
# fast = 3th
while fast: # 注意!不是fast.next!!!! 如果是fast.next的话,在最后一次进入while时,fast=fast.next=None.对Nonetype.next是没有意义的会报错!!!
slow = slow.next
fast = fast.next
# slow = 3th
# fast = 5th
slow.next = slow.next.next
# 3th.next = 5th
return dummy_head.next
面试题 02.07. 链表相交
给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null
。题目数据 保证 整个链式结构中不存在环。
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3 输出:Intersected at '8' 解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。 从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。 在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
思路:
所谓交点,就是两个链表各自在某一个node指向了相同的next node。
如果两个链表最后有相同的部分,假设A是更长的链表,那么一定只可能是在index = len(A)-len(B)(对更长的链表记)之后的node。所以,先计算两个链表各自的长度,再算出index。对于这个index,找到对应在两个链表里的node位置,相当于两个指针,然后一起每次指向next,如果next相等,则可以merge。
Tips: A、B链表不一定谁最长,但可以假设A是最长的那个,做这种调换:
curA, curB = curB, curA
lengthA, lengthB = lengthB, lengthA
反正最后输出起始的相交节点即可,无所谓A、B到底是啥。
Solution:
class Solution(object):
def getIntersectionNode(self, headA, headB):
"""
:type head1, head1: ListNode
:rtype: ListNode
"""
lengthA,lengthB = 0,0
cur = headA
while cur:
cur = cur.next
lengthA += 1
cur = headB
while cur:
cur = cur.next
lengthB += 1
curA, curB = headA, headB
if lengthB<lengthA:
curA, curB = curB, curA
lengthA, lengthB = lengthB, lengthA
for _ in range(lengthB-lengthA):
curB = curB.next
while curA:
if curA == curB:
return curA
else:
curA = curA.next
curB = curB.next
return None