38.报数
报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:
-
1
-
11
-
21
-
1211
-
111221
1 被读作 “one 1” (“一个一”) , 即 11。
11 被读作 “two 1s” (“两个一”), 即 21。
21 被读作 “one 2”, “one 1” (“一个二” , “一个一”) , 即 1211。
给定一个正整数 n(1 ≤ n ≤ 30),输出报数序列的第 n 项。
注意:整数顺序将表示为一个字符串。
class Solution(object):
def countAndSay(self, n):
"""
:type n: int
:rtype: str
"""
if n==1: #类似于斐波拉契数,后面的数跟前面的数有关
return '1'
if n==2:
return '11' #进行i=3时的循环时,它的上一项为'11'
pre='11
for i in range(3,n+1): #用for循环不断去计算逼近最后一次
res='' #结果,每次报数都要初始化
cnt=1 #计数变量
length=len(pre) #遍历我们的上一项,所以记录它的长度
for j in range(1,length):
if pre[j-1]==pre[j]:
cnt+=1 #相等则加一
else:
res+=str(cnt)+pre[j-1] #一旦遇到不同的变量,就更新结果
cnt=1 #重置为1
res+=str(cnt)+pre[j] #把最后一项及它的数量加上
pre=res #保存上一次的结果
return res
上周的笔记里对本题的叙述不够详尽,本周再进行补充。
根据报数的特点,我们可以根据上一项的结果推导下一项。我们遍历上一项,辅以计数变量统计一下某些数字出现的次数,同时要不断保存上一项。
53.最大字序和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
进阶:
如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
class Solution(object):
def maxSubArray(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if len(nums)==1:
return nums[0]
else:
a=[nums[0]]
for i in range(1,len(nums)):
if nums[i-1]>0:
nums[i]=nums[i]+nums[i-1]
a.append(nums[i])
return max(a)
本题难度不大,可调试了很多次才通过。
关键在于,子序列必开始于正数(有正数存在时),用相邻两数之和去替换第二个数,并不断循环比较,替代。最终取替换后的最大数;若全是非正数,则要通过列表选择最大的那个数。
关于本题的进阶,分治法,待下周更新。
58.最后一个单词的长度
给定一个仅包含大小写字母和空格 ’ ’ 的字符串,返回其最后一个单词的长度。
如果不存在最后一个单词,请返回 0 。
说明:一个单词是指由字母组成,但不包含任何空格的字符串。
示例:
输入: “Hello World”
输出: 5
class Solution(object):
def lengthOfLastWord(self, s):
"""
:type s: str
:rtype: int
"""
a=[]
b=0
for i in s:
if i ==' ':
j=s.index(i)
a.append(j)
b+=1
if len(a)!=0:
return (len(s)-a[b-1]-1)
else:
return 0
上述解法不能解决连续空格的情况,求解决
66.加一
给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储一个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。
示例 1:
输入: [1,2,3]
输出: [1,2,4]
解释: 输入数组表示数字 123。
示例 2:
输入: [4,3,2,1]
输出: [4,3,2,2]
解释: 输入数组表示数字 4321。
class Solution(object):
def plusOne(self, digits):
"""
:type digits: List[int]
:rtype: List[int]
"""
a=0
b=0
for i in digits:
a=a+i*10**(len(digits)-b-1)
b=b+1
a=a+1
l=[]
while a>0:
b=a%10
l.append(b)
a=a//10
l.reverse()
return l
如果直接使用列表解决,难点在于进位,所以果断用简单粗暴的解法,列表元素转为数字,加一以后再转换回去。先前第九题回文数已经用过类似的且更难得转换方法了,在此不一一赘述。
67.二进制求和
给定两个二进制字符串,返回他们的和(用二进制表示)。
输入为非空字符串且只包含数字 1 和 0。
示例 1:
输入: a = “11”, b = “1”
输出: “100”
示例 2:
输入: a = “1010”, b = “1011”
输出: “10101”
class Solution(object):
def addBinary(self, a, b):
"""
:type a: str
:type b: str
:rtype: str
"""
num=int(a,2)+int(b,2)
ans=bin(num)
return ans[2:]
基本思路就是将二进制字符串转换为十进制,相加后在转换回二进制。一个偷懒操作就是用int( )和bin()函数,解决所有。但要注意,bin()函数得到的‘0bxxxxxxxx’,所以要取[2:]项。
函数积累:
int(x, base=10)
顺便记录一下python下各类进制转换
dec = int(input(“输入数字:”))
print(“十进制数为:”, dec)
print(“转换为二进制为:”, bin(dec))
print(“转换为八进制为:”, oct(dec))
print(“转换为十六进制为:”, hex(dec))
如果不偷懒的话,就有些麻烦了
class Solution(object):
def addBinary(self, a, b):
"""
:type a: str
:type b: str
:rtype: str
"""
num1=num2=0
z=0
while(1): #表示会循环执行后面的语句
if len(a) == 0:
break
num1=num1+pow(2,z)*int(a[-1])
a=a[:-1]
z+=1
z = 0
while (1):
if len(b) == 0:
break
num2 = num2 + pow(2, z) * int(b[-1])
b = b[:-1]
z += 1
sum = num1+num2
sum = str(bin(sum)[2:])
return sum
69.x的平方根
实现 int sqrt(int x) 函数。
计算并返回 x 的平方根,其中 x 是非负整数。
由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
示例 1:
输入: 4
输出: 2
示例 2:
输入: 8
输出: 2
说明: 8 的平方根是 2.82842…,
由于返回类型是整数,小数部分将被舍去。
class Solution(object):
def mySqrt(self, x):
"""
:type x: int
:rtype: int
"""
min = 0
max = x
mid = x//2
while min<=max:
m = mid*mid
if m>x:
max = mid-1
elif m<x:
min = mid+1
else:
return mid
break
mid = (min+max)//2
return mid
本题需要用到一个之前没有接触过的方法——二分查找,不过在高中学过类似思想,用二分法近似解方程的根。
首先,表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
应用到本题上,先取出上界x与下界0,中间值则为x//2。判断mid的平方与x的大小关系,相等就查找成功,返回并结束循环即可;前者大,更改上界为mid-1,计算新mid值,开始新循环;后者小,更改下界为mid+1,计算新mid,开始新循环。