• 分治法 | Leetcode分类练习 | Datawhale- 打卡(一)


    1.主要思想:

    将问题递归的分成若干个小问题,直至满足边界条件返回结果,最后将结果合并。

    2.使用场景:

    各子问题之间相互独立。

    3.Leetcode题解:

    169.多数元素

    • 题目

      给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于[n/2]的元素。
      你可以假设数组是非空的,并且给定的数组总是存在多数元素。

    • 思路

      • 边界条件:子数组中最少有一个元素
      • 拆分数据:将数组左右二分为两个子数组
      • 合并结果:子数组中只有一个元素时,该元素即为多数元素;左子数组的多数元素left和右子数组的多数元素right相等时,left即为所求;不等时则需要比较right和left在nums中的出现次数获得最终结果
    • 代码

      class Solution:
          def majorityElement(self, nums: List[int]) -> int:
              # 先设置边界条件
              if nums is None:
                  return None
              if len(nums) ==1:
                  return nums[0]
              # 拆分成小问题
              left = self.majorityElement(nums[:len(nums)//2])
              right = self.majorityElement(nums[len(nums)//2:])
              # 合并结果
              if left == right:
                  return left
              else:
                  if nums.count(left) > nums.count(right):
                      return left
                  else:
                      return right 
      
    • 扩展

      摩尔投票法,前提条件所求元素在数组中出现次数过半

      class Solution:
          def majorityElement(self, nums: List[int]) -> int:
              res_num = nums[0]
              count = 1
              for num in nums[1:]:
                  if num == res_num:
                      count += 1
                  elif count == 0:
                      count = 1
                      res_num = num
                  else:
                      count -= 1
              return res_num
      

      耗时最短的做法

      class Solution:
          def majorityElement(self, nums: List[int]) -> int:
              nums.sort()
              return nums[len(nums)//2]
      

    53. 最大子序和

    • 题目

      给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

    • 思路

      • 边界条件:子数组中最少有一个元素
      • 拆分数据:将数组左右二分为两个子数组
      • 合并结果:子数组中只有一个元素时,该元素即为所求结果;左子数组的结果left,右子数组的结果right和(从右到左计算左边的最大子序和+从左到右计算右边的最大子序和)中最大值即为所求
    • 代码

      class Solution:
          def maxSubArray(self, nums: List[int]) -> int:
              if nums is None:
                  return None
              nums_len = len(nums)
              if nums_len ==1:
                  return nums[0]
              left = self.maxSubArray(nums[:nums_len//2])
              right = self.maxSubArray(nums[nums_len//2:])
              # 从右至左计算左边子数组的最大子序和
              max_l = nums[nums_len//2-1]
              temp = 0
              for left_i in range(nums_len//2-1,-1,-1):
                  temp += nums[left_i]
                  max_l = max(temp,max_l) 
              # 从左至右计算右边子数组的最大子序和
              max_r = nums[nums_len//2]
              temp = 0
              for right_i in range(nums_len//2,nums_len):
                  temp += nums[right_i]
                  max_r = max(temp,max_r) 
              return max(left,right,max_l+max_r)
      
    • 扩展

      因为负数相加,总和会越来越小,所以当子序列和小于等于0时,重新寻找新的连续子序列

      class Solution:
          def maxSubArray(self, nums: List[int]) -> int:
              max_sum = nums[0]
              mysum = 0
              for i in nums:
                  if mysum > 0:
                      mysum += i
                  else:
                      mysum = i
                  max_sum = max(mysum, max_sum)
              return max_sum
      

    50. Pow(x, n)

    • 题目

      实现 pow(x, n) ,即计算 x 的 n 次幂函数。

    • 思路

      • 边界条件:n 最后为0时返回1
      • 拆分数据:n除以2的余数为1时 n=n-1;否则n=n/2且x = x*x
      • 合并结果:n除以2的余数为1时计算结果并返回,为0时,更新x值,即将(x^2)带入myPow函数中
    • 代码

      class Solution:
          def myPow(self, x: float, n: int) -> float:
              if n < 0:
                  x = 1/x
                  n = -n
              if n == 0:
                  return 1
              if n%2 == 1:
                  return x * self.myPow(x,n-1)
              return self.myPow(x*x,n/2)
      
    • 扩展
      快速幂(二进制角度):通过增加底数减少幂运算次数,从而降低时间复杂度O(n)为O(logn)
      eg:Pow(2,10) 10的二进制写法是1010
      (2^{10} = 2^0 * 2^2 * 2^0 * 2^8 = 2^{2^1}*2^{2^3})

       class Solution:
          def myPow(self, x: float, n: int) -> float:
              if n < 0: 
                  x,n = 1/x,-n
              if n==0: 
                  return 1
              res = 1
              while n > 0:
                  # 判断最低位是否是1
                  if n&1:
                      res *= x
                  # 右移一位,相当于除以2
                  n=n>>1
                  x *= x
              return res   
      

    【参考】https://github.com/datawhalechina/team-learning-program/blob/master/LeetCodeClassification/1.分治.md#算法应用

  • 相关阅读:
    Cannot initialize Cluster. Please check your configuration for mapreduce.framework.name
    docker-compose 安装solr+ikanalyzer
    centos 安装Python3
    spring+springmvc+mybatis 开发JAVA单体应用
    职责链模式例子
    ssm(spring、springmvc、mybatis)框架整合
    PAT (Advanced Level) Practise
    PAT (Advanced Level) Practise
    PAT (Advanced Level) Practise
    PAT (Advanced Level) Practise
  • 原文地址:https://www.cnblogs.com/rn-05181226-rw/p/13523128.html
Copyright © 2020-2023  润新知