写在前面的话
慢慢转变思路,不再死磕不会做的题,思路可以先借鉴,但是一定要吃透透。
上周末看完看完了《算法图解》,感觉对一些题目的思路有比较大的帮助,但是还是要在实践中理解。
认真做题的分割线
第一题
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
我的思路:
这题做了两次,主体思路为:每次都找到乘积中的最大正值
和最小负值
,因为绝对值最大的两个数在下一次计算中才有可能成为最大值。(毕竟题目没有限制非负数)
第一次的时候报错的原因是,我记录了每次的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
我的思路:
条件一:要判断每次的值是否各位平方总和为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)
我的思路:
这个算法借鉴了评论里的一个炒鸡有趣的算法,默认查询是否质数的时候,我们习惯用循环判断,这样肯定会超时。
而这个算法呢,叫做厄拉多塞筛法
,他给了如下解释:
比如说求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)
总结
小李今天的做题,是痛并快乐着的!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。