递归与分治:题目手写50Pow(x,n)、169多数元素、122买卖股票的最佳时机

递归

深度优先搜索的基础。一种循环,自己调用自己。比如:盗梦空间

attention:递归出口,不然无限死循环。

eg1: 计算n!

def Factorial(n):
    #递归的出口
    if n<= 1:
        return 1
    return n * Factorial(n-1)

递归函数的形式:

def recursion(level,param1,param2,...):
    #递归的终止条件
    if level > MAX_LEVEL:
    print_sult
    return

    #当前层对数据操作
    process_data(level,data..)

    #下沉下一层,调用自己
    self.recursion(level+1,p1,...)

    #返回层时收尾工作(如果需要的话可以设计)
    reverse_state(level)

eg2: 费波拉契函数

费波拉契数组:1,1,2,3,5,8,13,21,34

通项公式: F(n) = F(n-1)+F(n-2)

def fib(n):
    if n==0 or n==1:
        return n
    return fib(n-1)+fib(n-2)

费波拉契数组中可以看出当问题有重复子问题时,用递归解决效率不高。可以使用判重或者记录结果解决。

分治-Dived&Conquer

递归常用来解决分治算法的问题,即先把一个大问题分解成很多个子问题,子问题再一一分析解决。

在这里插入图片描述

eg1:将一个字符串的每个字符变成大写

子问题之间互不影响,并行计算。

分治的代码结构:

def divide_conquer(problem,param1,param2...):

    #解决出口
    if problem is None:
        print_result
        return

    #准备数据
    data = prepare_data(problem)
    subproblems = split_problem(problem,data)

    #解决子问题
    subresult1 = self.divide_conquer(subproblems[0],p1,...)
    subresult2 = self.divide_conquer(subproblems[1],p1,...)
    subresult3 = self.divide_conquer(subproblems[2],p1,...)
    ...
    
    #处理最后的解集合
    result = process_result(subresult1,subresult2,subresult3...)

50.Pow(x, n)(中等)

来源: https://leetcode-cn.com/problems/powx-n/

题目: 实现 pow(x, n) ,即计算 x 的 n 次幂函数。 n可正可负。

思路1:暴力循法是可行的但是这题上没有意义,且会出现超时的情况。

这里采用分治的想法如图:

在这里插入图片描述

import math
class Solution(object):
    def myPow(self ,x, n):
        """
        :type x: float
        :type n: int
        :rtype: float
        """
        if n==0:return 1
        #if n==1:return x
        if n<0:
            return 1/self.myPow(x,-n)
        if n%2:
            return x*self.myPow(x,n-1)
        return self.myPow(x*x,n/2)

tips:这里有个问题就是,一开始我并没有明白是
( x 2 ) n / 2 (x^2)^{n/2} (x2)n/2
所以最后那个return 想不明白。如果好懂一点的话应该是

        if n%2:
            return x*self.myPow(x,n-1)
        res = self.myPow(x,n/2)
        return res*res

169.多元素数

来源:https://leetcode-cn.com/problems/majority-element/

题目:

给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素

示例:

输入: [3,2,3]
输出: 3

思路1:MAP方法。可以使用字典,对数组中所有元素使用循环建立字典,value存这个元素出现的次数。再一次循环找value值大于n/2的最小的整数。时间复杂度O(n)

import math
class Solution(object):
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        dic = {}
        res = []
        for i in range(len(nums)):
            dic[nums[i]] = dic.get(nums[i],0) + 1
        nums_1 = list(set(nums))
        for i in range(len(nums_1)):
            if dic.get(nums_1[i]) > math.ceil(len(nums)/2):
                return nums_1[i]

思路2:sort排序数组,排好之后,计算元素重复的的次数是否大于n/2。时间复杂度O(nlogn)。

思路3:视频给出了分治的方法,个人感觉有点牵强。不好理解不好写时间复杂度还是O(nlogn),总的来说这题并不适合分治。

实战:贪心算法Greedy

在对问题求解是,总是做出当前看来是最好的选择。

适用场景:问题能够分解成子问题来解决,子问题的最优解能地推到最终问题的最优解。这种子问题最优解成为最优子结构。

与==动态规划==的不同在于它对每个子问题的解决方案都做出选择,不能回退。动态规划则会保存以前的运算结果,并根据以前的结果对当前进行选择,有回退功能。

122.买卖股票的最佳时机

来源: https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/

题目:

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

来源: https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/

题目:

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

思路1:贪心算法,只要后一天的价格比今天高,那么今天买入,后一天卖出。
由于这是一个简单题,所以每天可以买卖无数次且买卖没有手续费,所以可以使用贪心算法,贪心算法的局限性还是很高的。其实这一题最好的方法是使用动态规划。后面学到了再说。

def maxProfit(self, prices):
    """
        :type prices: List[int]
        :rtype: int
        """
    res = 0
    for i in range(len(prices)-1):
        if prices[i+1]>prices[i]:
            res += prices[i+1]-prices[i]
    return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值