LeetCode160 相交链表
Write a program to find the node
at which the intersection of two singly linked lists begins.
For example, the following two linked lists:
思路一:哈希
将 headA 链表中每个节点存到集合中,遍历 headB 链表的每个节点
若存在集合中,则返回该相遇节点
若无存在集合中的节点,则返回 None。
代码出自LeetCode:160. 相交链表(python)。
class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None
class Solution(object):
def getIntersectionNode(self, headA, headB):
visited = set() # 存储节点
while headA: # 将 headA 各节点存在集合
visited.add(headA)
headA = headA.next
while headB: # 遍历 headB,若当前节点存在集合中,则为相交节点
if headB in visited:
return headB
headB = headB.next
return None
思路二:
双指针 curA、curB 分别从头部遍历 headA、headB 链表,当指针遍历至尾部时,指向另一个链表的头部,直至双指针在相交节点相遇,不相交时在空值处相遇。
class Solution(object):
def getIntersectionNode(self, headA, headB):
"""
:type head1, head1: ListNode
:rtype: ListNode
"""
p, q = headA, headB
while p != q:
q = headB if q is None else q.next
p = headA if p is None else p.next
return p
思路三:遍历两个链表,记录下各自的长度la,lb,则 abs(la-lb)为其中较长链表多出的几个节点,那么首先将长链表这几个节点跳过(为了好说明,这里假设较长链表为la,跳过多余节点后得到的链表为lc),此时,同时遍历lc和lb,若期间lc==lb,那么这个节点就是相交节点。
class Solution(object):
def getIntersectionNode(self, headA, headB):
"""
:type head1, head1: ListNode
:rtype: ListNode
"""
p, q = headA, headB
countA = countB = 0
while p != None:
p = p.next
countA += 1
while q != None:
q = q.next
countB += 1
m, n = headA, headB
if countA > countB:
for i in range(countA - countB):
m = m.next
else:
for i in range(countB - countA):
n = n.next
while m != n:
m = m.next
n = n.next
return m
思路二和思路三的解释和代码出自leetcode 160 python 相交链表。
LeetCode169 多数元素
Given an array nums of size n, return the majority element.
The majority element is the element that appears more than ⌊n / 2⌋ times.
You may assume that the majority element always exists in the array.
思路一:哈希表
用哈希表来快速统计每个元素出现的次数。
class Solution:
def majorityElement(self, nums):
counts = collections.Counter(nums)
return max(counts.keys(), key=counts.get)
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/majority-element/solution/duo-shu-yuan-su-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
思路二:排序
class Solution:
def majorityElement(self, nums):
nums.sort()
return nums[len(nums) // 2]
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/majority-element/solution/duo-shu-yuan-su-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
思路三:随机挑选
随机挑选一个下标对应的元素并验证,有很大的概率能找到众数。
import random
class Solution:
def majorityElement(self, nums):
majority_count = len(nums)//2
while True:
candidate = random.choice(nums)
if sum(1 for elem in nums if elem == candidate) > majority_count:
return candidate
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/majority-element/solution/duo-shu-yuan-su-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
思路四:分治法
将数组分成左右两部分,分别求出左半部分的众数 a1 以及右半部分的众数 a2,随后在 a1 和 a2 中选出正确的众数。
class Solution:
def majorityElement(self, nums, lo=0, hi=None):
def majority_element_rec(lo, hi):
# base case; the only element in an array of size 1 is the majority
# element.
if lo == hi:
return nums[lo]
# recurse on left and right halves of this slice.
mid = (hi-lo)//2 + lo
left = majority_element_rec(lo, mid)
right = majority_element_rec(mid+1, hi)
# if the two halves agree on the majority element, return it.
if left == right:
return left
# otherwise, count each element and return the "winner".
left_count = sum(1 for i in range(lo, hi+1) if nums[i] == left)
right_count = sum(1 for i in range(lo, hi+1) if nums[i] == right)
return left if left_count > right_count else right
return majority_element_rec(0, len(nums)-1)
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/majority-element/solution/duo-shu-yuan-su-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
思路五:Boyer-Moore 投票算法
把众数记为 +1+1,把其他数记为 -1−1,将它们全部加起来,显然和大于 0,从结果本身可以看出众数比其他数多。
class Solution:
def majorityElement(self, nums):
count = 0
candidate = None
for num in nums:
if count == 0:
candidate = num
count += (1 if num == candidate else -1)
return candidate
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/majority-element/solution/duo-shu-yuan-su-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
更详细的解释可以阅读LeetCode169 多数元素官方解决方案。
LeetCode206 反转链表
Reverse a singly linked list.
思路一:迭代
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
"""
迭代
"""
if (not head) or head.val==None: # 避免链表为空的特殊情况
return head
current_node = head
pre_node = None # 定义前一个点
while current_node: # 判断条件为当前点是否为None
next_node = current_node.next
current_node.next = pre_node
pre_node = current_node # 将前一个点定义为当前点
head = pre_node # 可以直接return pre_node,这么写是比较好理解
current_node = next_node # 定义下一个循环的当前节点为下一个节点
return head
迭代的另一种写法:用Python三元交换能同时赋值不需要缓存的特性可以一行完成交换。
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
"""
迭代之蛇皮走位写法
"""
current_node,pre_node = head,None
while current_node:
# 主要是利用了python的一个特性,在交换值的时候(以下式子),左边的值是暂时不变的
pre_node,current_node.next,current_node = current_node,pre_node,current_node.next
return pre_node
思路二:递归
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
"""
递归的写法
递归重要的是你要学会倒着考虑问题
"""
if not head or head.next == None: # 递归终止条件(以及排除特殊值问题)
return head
else:
newhead = self.reverseList(head.next) # newhead一直是指向最后一个节点
head.next.next = head
head.next = None # 仅仅在第一个元素时候起作用(递归就是一个栈,后进先出,所以先考虑末尾,最后考虑头)
return newhead
上述解释和代码均出自Python LeetCode-206.反转链表(难度-简单) 两个方法-迭代和递归,以及超简写法(python)。
任务链接:
team-learning-program/LeetCodeTencent/160 相交链表.md
team-learning-program/LeetCodeTencent/169 多数元素.md
team-learning-program/LeetCodeTencent/206 反转链表.md