Datawhale LeetCode腾讯精选50——Task13

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 相交链表

LeetCode160 相交链表官方解决方案

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)

LeetCode206 反转链表官方解决方案

任务链接:

team-learning-program/LeetCodeTencent/160 相交链表.md
team-learning-program/LeetCodeTencent/169 多数元素.md
team-learning-program/LeetCodeTencent/206 反转链表.md

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值