1

写在前面的话

慢慢转变思路,不再死磕不会做的题,思路可以先借鉴,但是一定要吃透透。
上周末看完看完了《算法图解》,感觉对一些题目的思路有比较大的帮助,但是还是要在实践中理解。

认真做题的分割线

第一题

152. 乘积最大子序列
难度:中等
给定一个整数数组nums,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。
我的题解:

class Solution(object):
    def maxProduct(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        length = len(nums)
        maxsum = [0 for _ in range(length)]
        minsum = [0 for _ in range(length)]
        maxsum[0] = minsum[0] = nums[0] # 限定最大最小值
        dp = nums[0] #当前状态
        for i in range(1,len(nums)):
            maxsum[i] = max(maxsum[i-1]*nums[i],minsum[i-1]*nums[i],nums[i])
            minsum[i] = min(maxsum[i-1]*nums[i],minsum[i-1]*nums[i],nums[i])
            dp = max(dp,maxsum[i])
        return dp

clipboard.png

我的思路:
这题做了两次,主体思路为:每次都找到乘积中的最大正值最小负值,因为绝对值最大的两个数在下一次计算中才有可能成为最大值。(毕竟题目没有限制非负数)
第一次的时候报错的原因是,我记录了每次的maxsum和minsum,没有记录上一次循环留下的值。
然鹅,上一次的状态会影响到下一次的状态,所以必须记住上一步的最优解。
可以判断是个NP问题,但是动态规划还得多多练习

第二题

202. 快乐数
难度:简单
编写一个算法来判断一个数是不是“快乐数”。

一个“快乐数”定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是无限循环但始终变不到 1。如果可以变为 1,那么这个数就是快乐数。
我的题解:

class Solution(object):
    def isHappy(self, n):
        """
        :type n: int
        :rtype: bool
        """
        l = []
        while 1:
            l.append(n)
            n = sum([int(i)**2 for i in str(n)])
            if n == 1:
                return True
            elif n in l:
                return False

clipboard.png

我的思路:
条件一:要判断每次的值是否各位平方总和为1,得出是快乐数的结论;
条件二:为了得出非快乐数的结论,这个数可能会陷入循环,那么就要记录下每轮的值,并进行比对。
其他:
在评论中发现了一个很有趣的算法,就是用dict记录下肯定会循环的数字的词典,当遇到相关数字的时候就可以跳出了。
一般为{4,16,37,58,89,145,42,20}

第三题

204. 计数质数
难度:简单
统计所有小于非负整数 n 的质数的数量。
我的题解:

class Solution(object):
    def countPrimes(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n < 3:
            return 0
        else:
            output = [1]*n
            output[0],output[1] = 0,0
            for i in range(2,int(n**0.5+1)):
                if output[i] == 1:
                    m = i**2
                    while m < n:
                        output[m] = 0
                        m += i
        return sum(output)

clipboard.png

我的思路:
这个算法借鉴了评论里的一个炒鸡有趣的算法,默认查询是否质数的时候,我们习惯用循环判断,这样肯定会超时。
而这个算法呢,叫做厄拉多塞筛法,他给了如下解释:

比如说求20以内质数的个数,首先0,1不是质数.2是第一个质数,然后把20以内所有2的倍数划去.2后面紧跟的数即为下一个质数3,然后把3所有的倍数划去.3后面紧跟的数即为下一个质数5,再把5所有的倍数划去.以此类推

包括他的题解的写法也很有趣,但是我还没弄明白
output[i*i:n:i] = [0] * len(output[i*i:n:i])这一句的意思,还要琢磨下,所以用的是循环的写法。

def countPrimes(self, n: int) -> int:
        if n < 3:
            return 0     
        else:
            # 首先生成了一个全部为1的列表
            output = [1] * n
            # 因为0和1不是质数,所以列表的前两个位置赋值为0
            output[0],output[1] = 0,0
             # 此时从index = 2开始遍历,output[2]==1,即表明第一个质数为2,然后将2的倍数对应的索引
             # 全部赋值为0. 此时output[3] == 1,即表明下一个质数为3,同样划去3的倍数.以此类推.
            for i in range(2,int(n**0.5)+1): 
                if output[i] == 1:
                    output[i*i:n:i] = [0] * len(output[i*i:n:i])
         # 最后output中的数字1表明该位置上的索引数为质数,然后求和即可.
        return sum(output)

总结

小李今天的做题,是痛并快乐着的!


林奈木
35 声望7 粉丝

深水静流。