leetcode 119/121/161简单题题解 python3

119题 杨辉三角2

用迭代做:

class Solution:
    def getRow(self, rowIndex: int) -> List[int]:
        whole = []
        for row_order in range(rowIndex + 1):
            therow = [1] * (row_order + 1)
            for j in range(1, row_order):
                therow[j] = whole[row_order-1][j-1] + whole[row_order-1][j]
            whole.append(therow)
        return whole[rowIndex]

空间复杂度应该是n^2.

我一直在考虑用递归怎么去做,在题解里看到一个思路(来源用户 1501615430):只做一个数组,但是对它做滚动处理,从右至左从len-2的位置依次加上前位,这是利用杨辉三角本身的数学原理去做一个“递归”。空间复杂度只有n,两个时间复杂度都是n^2

class Solution:
    def getRow(self, rowIndex: int) -> List[int]:
        therow = [1]
        for i in range(rowIndex):
            therow.append(1)
            for j in range(len(therow)-2, 0, -1):
                therow[j] += therow[j-1]
        return therow

121题 买卖股票的最佳时机

乍一看这个题挺简单的,写了两个时间复杂度分别为n^2和n的,竟然都超时,可能因为用了遍历比较。看了题解才知道正确解法,所以题都是有章法的而不是自己乱写迭代...

方法一: 迭代- 超时题解(官方给的,我自己本身的还加了一个列表

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        ans = 0
        for i in range(len(prices)):
            for j in range(i + 1, len(prices)):
                ans = max(ans, prices[j] - prices[i])
        return ans

方法二:一次遍历,计算到当天为止的最小价格和最大利润(以下两个方法都来自于用户 腐烂的橘子 题解。)

其实它的本质和动态规划很像,状态转移方程是一样的,虽然也用了max和比较,但是只是在两个之间比较,而不是遍历比较,就会省很多内存。

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        minprice = float('inf')
        maxprofit = 0
        for price in prices:
            minprice = min(minprice, price)
            maxprofit = max(maxprofit, price - minprice)
        return maxprofit

方法三:动态规划

找出dp[0], dp[i], dp[i]与dp[i-1]的状态转移方程,就ok

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        minprice = prices[0]
        dp = [0] * len(prices)
        dp[0] = 0
        for i in range(1, len(prices)):
            minprice = min(prices[i], minprice)
            dp[i] = max(dp[i-1], prices[i] - minprice)
        return dp[len(prices)-1]

所以其实方法二和方法三没啥区别,而且方法三的空间复杂度更高,消耗内存多。为什么方法二的minprice是inf而方法三的是prices[0]呢?

我个人认为方法二是从0位置开始遍历,而方法三是从1位开始,会忽视掉0位的价格。所以必须放进去,实质上方法二写成prices[0]也没有任何问题。

167题 两数之和2 

这道题很不难,但是有一些学习心得。

方法一: 做这个题的暴力解法,是没有考虑有序性质的,而且时间复杂度O(n2),超时。

方法二: 二分查找。定一个值,用二分法找它与target的差值,遍历一次数组,时间复杂度O(nlogn).

方法三: 双指针。从两边向中间查找,两个指针避免了遍历,大大减少了运行时间和内存的消耗,时间复杂度O(n). 双指针肯定是要更省时间的!

方法四: 一次哈希表。这个方法非常有意思,把哈希思想体现的淋漓尽致。定一个值加为字典的value(即为较小数值索引值),其key就是与target的差值。若遍历至此key,则存在于字典中,此时的索引值即为较大数值索引值。答案就出来了。虽然效率很低,但是思路很有趣

class Solution:
    def twoSum(self, numbers: List[int], target: int) -> List[int]:
        dict_helper = {}
        for i in range(len(numbers)):
            if numbers[i] in dict_helper:
                return [dict_helper[numbers[i]]+1, i+1] 
                #这里的i是较大数索引,较小数索引为较大数的value
            else:
                dict_helper[target - numbers[i]] = i 
                #这里i是较小数的索引,key是较大数

心得: 暴力解法行不通我就在思考,怎么才能降低时间复杂度,想到了二分法,但是脑子里走马观花觉得也省不了多少事......就放弃了,可实际上时间复杂度就是少了很多也就可以通过。所以不能“主观臆断”,要有依据和逻辑。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值