文章目录
2019/9/21:回文数
题目链接:https://leetcode-cn.com/problems/palindrome-number/
这题考虑两种方式,转换成字符串或者就用整数本身进行操作:
class Solution(object):
def isPalindrome(self, x):
"""
:type x: int
:rtype: bool
"""
return True if str(x)==str(x)[::-1] else False
直接整数考虑可以这样:
首先用一个变量记录数字的最高位,比如12321,可以标记为help为10000,第一个末位为1,第一个首位为12321/10000=1,接下来我们需要计算232是否为回文。我们需要去掉首位和末位。可以采用x % help / 10的方式,12321%10000 ==2321可以将最高位去掉,然后2321/10 ==232可以将最低为去掉。最后不要忘记将help/100
class Solution(object):
def isPalindrome(self, x):
"""
:type x: int
:rtype: bool
"""
if x < 0:
return False
help = 1
temp = x
while temp >= 10:
help *= 10
temp //= 10
while x != 0:
if x % 10 != x // help:
return False
x = x % help // 10
help //= 100
return True
2019/9/22:字符串转换整数 (atoi)
题目链接:https://leetcode-cn.com/problems/string-to-integer-atoi/
class Solution:
def myAtoi(self, s: str) -> int:
return max(min(int(*re.findall('^[\+\-]?\d+', s.lstrip())), 2**31 - 1), -2**31) # 因为findall返回的是一个列表,并且其中只有一个元素,是可迭代对象,所以可以解包,另外就是做大小值判断了
"""
^:匹配字符串开头
[\+\-]:代表一个+字符或-字符
?:前面一个字符可有可无
\d:一个数字
+:前面一个字符的一个或多个
\D:一个非数字字符
*:前面一个字符的0个或多个
"""
如果不用正则,应该是下面这种方案:
class Solution(object):
def myAtoi(self, str):
"""
:type str: str
:rtype: int
"""
#去掉左边字符
str=str.lstrip()
#如果字符串空,返回
if len(str)==0:
return 0
#设置默认输出为0
last=0
#如果有符号设置起始位置2,其余的为1
i=2 if str[0]=='-'or str[0]=='+' else 1
#循环,直到无法强转成int,跳出循环
while i <= len(str):
try:
last=int(str[:i])
i+=1
except:
break
#如果数字超出范围,返回范围最大值
if last<-2147483648 :
return -2147483648
if last>2147483647:
return 2147483647
return last
2019/9/26:两数相加与字符串相乘
题目链接:https://leetcode-cn.com/problems/add-strings/
题目中意思可以理解为要我们重新模拟一下两数相加和两数相乘的步骤,首先来看两数相加,我们可以考虑用双指针的解法对其进行解答:
class Solution(object):
def addStrings(self, num1, num2):
"""
:type num1: str
:type num2: str
:rtype: str
"""
i,j,carry = len(num1) - 1,len(num2) - 1,0
res = ""
while i >= 0 and j >= 0:
n1 = int(num1[i]) if i >= 0 else 0 # 从末尾开始取并进行补0操作,如果num1的前面位数小于num2,那么将None替换成0
n2 = int(num2[j]) if j >= 0 else 0
tmp = n1 + n2 + carry
print(tmp)
carry = tmp // 10
res = str(tmp % 10) + res
i , j = i - 1,j - 1
return "1" + res if carry else res
然后关于两数相乘,不太清楚什么是BigInteger,感觉好像只有下面这种满足了题意,但有点复杂,所以以后回过头来复习的时候再看吧。
Python 字符串暴力模拟竖式乘法计算过程
2019/9/26:反转字符串
题目链接:https://leetcode-cn.com/problems/reverse-string/comments/
因为看到标题是双指针了,所以这题应该就是考双指针概念,很容易就写出代码:
class Solution(object):
def reverseString(self, s):
"""
:type s: List[str]
:rtype: None Do not return anything, modify s in-place instead.
"""
prev,cur = 0,len(s) - 1
while prev < cur:
s[prev],s[cur] = s[cur],s[prev]
prev,cur = prev + 1,cur - 1
if prev >= cur:
return s
else:
continue
2019/9/26:反转字符串中的单词 III
题目链接:https://leetcode-cn.com/problems/reverse-words-in-a-string-iii/
题目很简单,直接写出代码为:
class Solution(object):
def reverseWords(self, s):
"""
:type s: str
:rtype: str
"""
c = a.split()
for i in range(len(c)):
c[i] = c[i][::-1]
s = " ".join(c)
return s
""" return " ".join([i[::-1] for i in a.split()]) """
2019/9/26:最长公共前缀
题目链接:https://leetcode-cn.com/problems/longest-common-prefix/
拿到数组中最长的字符串和最短的字符串,遍历最短的字符串防止索引超出界限,然后比照有多少相同的前缀:
class Solution(object):
def longestCommonPrefix(self, strs):
"""
:type strs: List[str]
:rtype: str
"""
if not strs: return ""
s1 = min(strs)
s2 = max(strs)
for i,x in enumerate(s1):
if x != s2[i]:
return s2[:i]
return s1
方案二是通过python的内置函数去取数,利用python的zip函数,把str看成list然后把输入看成二维数组,左对齐纵向压缩,然后把每项利用集合去重,之后遍历list中找到元素长度大于1之前的就是公共前缀:
class Solution(object):
def longestCommonPrefix(self, strs):
"""
:type strs: List[str]
:rtype: str
"""
if not strs: return ""
ss = list(map(set, zip(*strs)))
res = ""
for i, x in enumerate(ss):
x = list(x)
if len(x) > 1:
break
res = res + x[0]
return res
2019/9/27:最大子序和
题目链接:https://leetcode-cn.com/problems/maximum-subarray/
这题有两种方式,第一种是动态规划,因为有很确的求一个最大值的和,另一种就是分治法。
那么动态规划可以这样写:
class Solution(object):
def maxSubArray(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
for i in range(1, len(nums)):
# 当前索引i永远存储0~i的最大和
nums[i] = max(nums[i], nums[i] + nums[i - 1])
# 返回每个索引最大和的最大值
return max(nums)
分治法为:
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
n = len(nums)
#递归终止条件
if n == 1:
return nums[0]
else:
#递归计算左半边最大子序和
max_left = self.maxSubArray(nums[0:len(nums) // 2])
#递归计算右半边最大子序和
max_right = self.maxSubArray(nums[len(nums) // 2:len(nums)])
#计算中间的最大子序和,从右到左计算左边的最大子序和,从左到右计算右边的最大子序和,再相加
max_l = nums[len(nums) // 2 - 1]
tmp = 0
for i in range(len(nums) // 2 - 1, -1, -1):
tmp += nums[i]
max_l = max(tmp, max_l)
max_r = nums[len(nums) // 2]
tmp = 0
for i in range(len(nums) // 2, len(nums)):
tmp += nums[i]
max_r = max(tmp, max_r)
#返回三个中的最大值
return max(max_right,max_left,max_l+max_r)
2019/9/27:格雷编码
题目链接:https://leetcode-cn.com/problems/gray-code/
class Solution:
def grayCode(self, n: int) -> List[int]:
if n==0:
return [0]
res=[]
def back(now,x):
if len(now)==n:
res.append(int(now,2))
elif x==0:
back(now+'0',0)
back(now+'1',1)
else:
back(now+'1',0)
back(now+'0',1)
back('',0)
return res
2019/9/27:全排列
题目链接:https://leetcode-cn.com/problems/permutations/
这题开始想到两种方式,第一种就是python中有一个排列模块,和前面子集类似,然后很快就可以想到这种方式,代码为:
from itertools import permutations
class Solution(object):
def permute(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
n = len(nums)
res = []
for i in permutations(nums,n):
res.append(i)
return res
第二种就是按照题目需求,自己写一个回朔算法了:
class Solution:
# 利用“回溯法”找到所有排列。
# 回溯法的重点1:利用全局变量记录状态。
# 回溯法的重点2:利用循环+条件判断,判断是否进行下一步探索(回溯)。
def search(self, nums, res, result):
# 利用两个全局变量,res用于记录每次回溯的结果状态,result用于记录最后
# 完全满足条件的res。
if len(res) == len(nums):
result.append(res.copy())
else:
# 利用for循环去探索可能情况
for i in range(len(nums)):
# 筛选符合条件的
if nums[i] not in res:
# 用res记录下这次回溯的结果
res.append(nums[i])
# 将nums,res,result往下回溯
self.search(nums, res, result)
# 一定记住在程序的出口,也就是下次探索之前,一定要将本次的状态记录删除
# 因为,res是在回溯之间的全局变量,下次可能性探索之前没有将本次的记录
# 的记录删除,那么下次探索就会包含本次探索的结果,会造成严重的错误。
res.pop()
def permute(self, nums: List[int]) -> List[List[int]]:
result = []
res = []
self.search(nums, res, result)
return result