数据结构与算法之分治、回溯

142 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 8 天,点击查看活动详情

作者: 千石
支持:点赞、收藏、评论
欢迎各位在评论区交流

前言

本文内容来自我平时学习的一些积累,如有错误,还请指正

在题目实战部分,我将代码实现和代码解释设置在了解题思路的下方,方便各位作为参考刷题

本文大纲

分治、回溯.png

一些话

本文内容来自我平时学习的一些积累,如有错误,还请指正

在题目实战部分,我将代码实现和代码解释设置在了解题思路的下方,方便各位作为参考刷题

题目练习步骤:

  1. 给自己10分钟,读题并思考解题思路
  2. 有了思路以后开始写代码,如果在上一步骤中没有思路则停止思考并且看该题题解
  3. 在看懂题解(暂时没看懂也没关系)的思路后,背诵默写题解,直至能熟练写出来
  4. 隔一段时间,再次尝试写这道题目

前置知识

分治法是一种被称为“分而治之”的策略,它把一个复杂的问题划分为若干个相对简单的子问题,然后递归地解决这些子问题,最终获得原问题的解。

回溯法是一种试错法,它尝试利用搜索树来遍历所有可能的状态和解法,以寻找问题的最优解。回溯法的核心思想是搜索,采用试错的方式对问题进行求解,通过对问题的所有可能解进行逐个检查,来寻找问题的最优解。

题目

169. 多数元素

image.png

开始解答

将数组分成两半,递归查找每个半部分的多数元素来实现。当只剩下一个元素时,这个元素就是我们的多数元素要找到多数元素,您可以使用一种叫做投票法的方法。它的工作原理是计数每个元素出现的次数,然后返回出现次数最多的元素。

这种方法的复杂度为O(n)。

class Solution: 
  def majorityElement(self, nums): 
    
    # Divide and conquer
    if len(nums) == 1: 
        return nums[0] 
  
    mid = len(nums)//2
    left_elem = self.majorityElement(nums[:mid]) 
    right_elem = self.majorityElement(nums[mid:]) 
  
    if left_elem == right_elem: 
        return left_elem 
  
    left_count = sum(1 for i in nums if i == left_elem) 
    right_count = sum(1 for i in nums if i == right_elem) 
  
    return left_elem if left_count > right_count else right_elem

17. 电话号码的字母组合

以每个数字为划分点,把问题分而治之,递归地解决子问题。首先声明一个字典m,它用来将数字映射成对应的字母。然后定义一个结果列表result,初始化为一个空字符串。接下来遍历数字字符串中的每个数字,对于每个数字,循环 result 中的每一项,然后把 m[num] 中的每一个字母拼接到 result 中对应的项上,最后把临时列表 tmp 重新赋值给 result,遍历完所有数字时, result 就是答案。

class Solution:
def letterCombinations(self, digits):
    if not digits:
        return []
    m = {'2': 'abc', '3': 'def', '4': 'ghi', '5': 'jkl', 
            '6': 'mno', '7': 'pqrs', '8': 'tuv', '9': 'wxyz'}
    result = ['']
    for num in digits:
        tmp = []
        for y in result:
            for x in m[num]:
                tmp.append(y+x)
        result = tmp
    return result