删除排序链表的重复元素
题目描述
给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。
示例
输入:1->1->2
返回值:1->2
解题思路
因为链表是升序排列的,所以只要按顺序循环,如果发现下一节点的val等于当前节点的val,直接将next指向next.next即可。
class ListNode(object):
"""docstring for ListNode"""
def __init__(self, x):
self.val = x
self.next = None
class Solution(object):
"""docstring for Solution"""
def deleteDuplicates(self, head):
p = head
if p == None or p.next == None: return head
while p.next:
if p.val == p.next.val:
p.next= p.next.next
else:
p = p.next
return head
- 时间复杂度:O(n)
- 空间复杂度:O(1)
合并两个有序链表
题目描述
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例
输入:1->2->4, 1->3->4
返回值:1->1->2->3->4->4
解题思路
新定义一个链表首节点dump指向0,当l1和l2链表均不为空时,判断l1当前节点val值与l2当前节点val值,如果l1当前节点val值大则当前指针指向l1,否则指向l2。直至循环结束,返回dump.next。
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
"""docstring for Solution"""
def merge(self, l1, l2):
if not l1: return l2
if not l2: return l1
cur = dump = ListNode(0)
while l1 and l2:
if l1.val >= l2.val:
cur.next = l2
l2 = l2.next
cur = cur.next
else:
cur.next = l1
l1 = l1.next
cur = cur.next
cur.next = l1 if l1 else l2
return dump.next
- 时间复杂度:O(n)
- 空间复杂度:O(n)
反转链表
题目描述
输入一个链表,反转链表后,输出新链表的表头。
示例
输入:{1,2,3}
返回值:{3,2,1}
解题思路
定义3个listNode,一个cur(指向当前节点,初始赋值head),一个pre(指向上一个节点,初始赋值None),一个指向nex(指向下一个节点,初始赋值None)。当cur非空时,nex指向cur.next,cur.next指向pre,pre指向cur,cur指向next。
class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None
class Solution(object):
def reverseList(self, pHead):
cur = pHead
nex = None
pre = None
while cur:
nex = cur.next
cur.next = pre
pre = cur
cur = nex
return pre
node1 = ListNode(1)
node2 = ListNode(3)
node3 = ListNode(7)
node1.next = node2
node2.next = node3
solution = Solution()
h = solution.reverseList(node1)
- 时间复杂度:O(n)
- 空间复杂度:O(1)
判断链表中是否有环
题目描述
判断给定的链表中是否有环 扩展: 你能给出空间复杂度O(1)的解法么?
示例
有环返回true;否则返回false
解题思路
使用快慢指针,快指针比慢指针移动快一倍,如果链表有环,则快慢指针会相遇。如果无环,快指针会循环至空,即结束循环返回false
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def hasCycle(self, head):
if head:
slow, fast = head, head.next
while fast:
slow = slow.next
fast = fast.next
if fast is slow:
return True
if fast:
fast = fast.next
return False
- 时间复杂度:O(n)
- 空间复杂度:O(1)
返回链表入环节点
题目描述
给定一个链表,返回链表开始入环的第一个节点。如果链表无环,则返回null。
说明:不允许修改给定的链表。
进阶:你是否可以使用 O(1) 空间解决此题?
示例
有环返回入环的第一个节点;否则返回null
解题思路
假设相交点为a,使用快慢指针,快指针步长是慢指针的2倍,得到快慢指针相交点为b。此时慢指针从head走到a的距离加上a走到b的距离乘以2等于快指针从head走到a的距离+从a走到b的距离+从b走到a的距离+从a走到b的距离,即从head走到a的距离等于从b走到a的距离。detection指向head,跟slow指针同步往下走,相交点即入环点。
class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None
class Solution(object):
def detectCycle(self, head):
if head and head.next:
slow = head.next
fast = head.next.next
else:
return None
while fast:
if fast != slow:
if fast.next:
fast = fast.next.next
else:
return None
slow = slow.next
else:
detection = head
while detection != slow:
slow = slow.next
detection = detection.next
return detection
- 时间复杂度:O(n)
- 空间复杂度:O(1)
判断一个链表是否为回文结构
题目描述
给定一个链表,请判断该链表是否为回文结构。 扩展: 你能给出空间复杂度O(1)的解法么?
示例
是则返回true;否则返回false
解题思路
想要空间复杂度胃O(1),可以先使用快慢指针找到链表的中间点,然后将后半段链表反转,跟前半段链表进行对比,如果相等则返回true
class ListNode(object):
"""docstring for ListNode"""
def __init__(self, x):
self.val = x
self.next = None
class Solution(object):
"""docstring for Solution"""
def isPail_List(self, head):
if head is None or head.next is None: return True
if head.next.next == None: return head.val == head.next.val
fast = slow = q = head
while fast.next and fast.next.next:
fast = fast.next.next
slow = slow.next
def reverse_List(head):
cur = head
nex = None
pre = None
while cur:
nex = cur.next
cur.next = pre
pre = cur
cur = nex
return pre
p = reverse_List(slow.next)
while p.next:
if p.val != q.val:
return False
p = p.next
q = q.next
return p.val == q.val
- 时间复杂度:O(n)
- 空间复杂度:O(1)
相交链表
题目描述
编写一个程序,找到两个单链表相交的起始节点。
示例
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Reference of the node with value = 8 输入解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
解题思路
假设headA到相交点的距离为a,headB到相交点的距离为b,相交后的链表长度为c。因为a+c+b = b+c+a,分别定义p和q遍历l1和l2,遍历到链表结尾时p和q已经走过了l1和l2的差值,然后p、q分别移动到另一链表的表头。如果相交,则返回相交点,如果都遍历至null,则null==null退出循环
class ListNode(object):
"""docstring for ListNode"""
def __init__(self, x):
self.val = x
self.next = None
class Solution(object):
"""docstring for Solution"""
def getIntersectionNode(self, headA, headB):
p = headA
q = headB
while p != q:
p = p.next if p else headB
q = q.next if q else headA
return p
- 时间复杂度:O(n)
- 空间复杂度:O(1)