今后我将会做Leedcode专题,将我做题的分析和代码记录下来。所有题目都来源于https://leetcode-cn.com。所有的语言都用python编写。
本篇难度:简答
习题一:两数之合
题目:
1.给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:
给定 nums = [2, 7, 11, 15], target = 9,因为 nums[0] + nums[1] = 2 + 7 = 9,所以返回 [0, 1]
解题思路:
①题中很明确的说只有一个输出结果,因此不可能出现列表中有多个相同的元素的情况。
②我们可以采用循环的方法逐个查找,但是考虑到耗时问题,不能暴力查找。
③核心:num1+num2=target
# 方法1:
def twoSum(nums, target):
lens = len(nums)
j=-1
for i in range(lens):
if (target - nums[i]) in nums:
#如果num2=num1,且nums中只出现了一次,说明找到是num1本身。
if (nums.count(target - nums[i]) == 1)&(target - nums[i] == nums[i]):
continue
else:
j = nums.index(target - nums[i],i+1) #index(x,i+1)是从num1后的序列后找num2
break
if j>0:
return [i,j]
else:
return []
# 可以学到:
# nums.count(x)可以得到列表nums中x出现的次数
# nums.index(x)返回的是列表nums中元素x的索引
----------------------------------------------------------------------------
# 方法2:
def twoSum(nums, target):
lens = len(nums)
j=-1
for i in range(1,lens):
temp = nums[:i]
if (target - nums[i]) in temp:
j = temp.index(target - nums[i])
break
if j>=0:
return [j,i]
-----------------------------------------------------------------------------
# 方法3:
def twoSum(nums, target):
hashmap={}
for ind,num in enumerate(nums):
hashmap[num] = ind
for i,num in enumerate(nums):
j = hashmap.get(target - num)
if j is not None and i!=j:
return [i,j]
# 可以学到:
# 这里通过字典来模拟哈希查询的过程
# 当用for循环查找索引和值的时候,可以用enumerate(nums),返回索引和值
# hashmap.get(x),返回字典中key为x的value值
-----------------------------------------------------------------------------
# 方法4:
# 这是方法3的优化
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hashmap={}
for i,num in enumerate(nums):
if hashmap.get(target - num) is not None:
if i<hashmap.get(target - num):
return [i,hashmap.get(target - num)]
else:
return [hashmap.get(target - num),i]
hashmap[num] = i
习题二:整数反转
题目:
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。注意:假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。
示例:
输入: 123 输出: 321; 输入: -123 输出: -321 ;输入: 120 输出: 21
解题思路 :
将整数先去符号,然后转换成字符串或者列表,将其反转。
# 方法1:
# 整数去符号—变成字符串—变成列表—反转—再变成字符串
class Solution:
def reverse(self, x: int) -> int:
#将整数的绝对值转换成字符串
s=str(abs(x))
#字符串变成列表
s=list(s)
#列表反转
s.reverse()
#列表变成字符串
s=''.join(s)
#如果输入整数是负数,增加负号
if x <0:
s ='-' + s
#转换为整数
result = int(s)
#判断是否溢出
if result>=-2**31 and result<=2**31-1:
return result
else:
return 0
----------------------------------------------------------------
# 方法2:
# 整数去符号—变成字符串—反转
class Solution:
def reverse(self, x: int) -> int:
#将整数的绝对值转换成字符串
s=str(abs(x))
#翻转字符串
s=s[::-1]
#如果输入整数是负数,增加负号
if x <0:
s ='-' + s
#转换为整数
result = int(s)
#判断是否溢出
if result>=-2**31 and result<=2**31-1:
return result
else:
return 0
# 可以学到:
# 整数、字符串、列表之间的转换关系要注意,熟悉操作以便简化代码
习题三:回文数
题目:
判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
示例:
输入: -121 输出: false 解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
解题思路:
此题和第二题类似,都是采用字符串反转来判断。这里要注意的是函数的返回值是一个已经定义的变量求得的结果,不能用return false来表示,因为false没有定义。
# 方法1:
# 此方法可以在leedcode中通过
class Solution:
def isPalindrome(self, x: int) -> bool:
# 转换成字符串
x=str(x)
# 字符串反转
s=x[::-1]
return x==s
---------------------------------------------------------
# 方法2:
# 此方法只能在编译器通过 ,因为leedcode中会把'flase'和'true'当成字符串,而不是布尔值
class Solution:
def isPalindrome(self, x: int) -> bool:
if x < 0:
return 'false'
else:
s1=str(x)
s2=s1[::-1]
if s1==s2:
return 'true'
else:
return 'false'
习题四:罗马数字转整数
题目:
罗马数字包含以下七种字符: I
, V
, X
, L
,C
,D
和 M。
字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
- I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
- X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
- C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。
示例:
输入: "MCMXCIV"
输出: 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.
解题思路:
①用字典将这些key-value对存入其中。
②通过观察,我们可以发现,正常来说大的字符在前,小的字符在后。由于6种特殊情况是小的字符在大的字符前面,因此当从左到右遍历的时候,碰到s[i]<s[i+1]就用sum减去x[i]即可。
class Solution:
def romanToInt(self, s: str) -> int:
dic={'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
sum=0
for i in range(len(s)-1):
if dic[s[i]]>=dic[s[i+1]]:
sum=sum+dic[s[i]]
else:
sum=sum-dic[s[i]]
sum=sum+dic[s[-1]]
return sum
习题五:最长公共前缀
题目:
编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 ""
。所有输入只包含小写字母 a-z
。
示例:
输入: ["flower","flow","flight"]
输出: "fl"
解题思路:
①两两比较
②为了节约空间,每次都是比较列表最后两个字符串,把比较的结果放在列表倒数第二个位置,把列表最后一个位置元素删除。
# 方法1:
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
# 空串
if not strs:
return ''
# 只有1个元素,自己和自己比较
elif len(strs)==1:
return strs[0]
else:
# 等于1的时候,就是最后的结果了
while len(strs)!=1:
a=strs[-1]
b=strs[-2]
i=0
res=''
while i<len(a) and i<len(b):
if a[i]==b[i]:
res=res+a[i]
i+=1
else:
break
strs[-2]=res
strs.pop()
return res
--------------------------------------------------------------
# 方法2:
class Solution(object):
def longestCommonPrefix(self, strs):
ans = ''
for i in zip(*strs):
# set(i)是去重,如果都一样的话 ,只保留一个,因此结果为1
if len(set(i)) == 1:
# 如果去重成功,则是公共前缀,因此要取一个,这里取第一个最简单
ans += i[0]
else:
break
return ans
# 可以学到:
# zip(*strs)返回一个以元组为元素的列表,其中第i个元组包含每个参数序列的第i个元素。返回的列表长度被截断为最短的参数序列的长度。
# 如下是zip(*a)的结果
a= ["flower","flow","flight"]
b=zip(*a)
for i in b:
print(i)
('f', 'f', 'f')
('l', 'l', 'l')
('o', 'o', 'i')
('w', 'w', 'g')