2020 08/05
给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i
的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器,且 n 的值至少为 2。 图中垂直线代表输入数组
[1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。 示例:
输入:[1,8,6,2,5,4,8,3,7] 输出:49
双指针题,这种需要从两端开始往中间遍历得题目,主要是你得能想到是双指针,而且,搞好指针变动的规律,这里就是哪边得低则那边就往另一个方向移动。
class Solution(object):
def maxArea(self, height):
"""
:type height: List[int]
:rtype: int
"""
# 从两端开始,每次固定长边,移动短边,同时那些如果移动后比移动前得边短得边不需要计算容量
s = 0
e = len(height) - 1
maxV = 0
while s < e:
save = s
short = s if height[s] < height[e] else e
area = height[short] * (e-s)
maxV = area if area > maxV else maxV
s = s if height[s] > height[e] else (s+1)
e = e if height[e] > height[save] else (e-1)
return maxV
还可以做一些优化,就是两边指针移动得时候,对于移动后的高度还不如之前的那些边就可以不用去计算面积,与因为长度已经短了,你如果高度还低了,那肯定不会是最大得面积。
2020 08/11
罗马数字包含以下七种字符: 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 的范围内。 示例 1: 输入: 3 输出: “III” 示例 2: 输入: 4
输出: “IV” 示例 3: 输入: 9 输出: “IX” 示例 4: 输入: 58 输出: “LVIII” 解释: L = 50, V =
5, III = 3. 示例 5: 输入: 1994 输出: “MCMXCIV” 解释: M = 1000, CM = 900, XC =
90, IV = 4.
class Solution(object):
def intToRoman(self, num):
"""
:type num: int
:rtype: str
"""
roman1 = {1:"I",2:"II",3:"III",4:"IV",5:"V",6:"VI",7:"VII",8:"VIII",9:"IX",10:"X"}
roman2 = {1:"X",2:"XX",3:"XXX",4:"XL",5:"L",6:"LX",7:"LXX",8:"LXXX",9:"XC",10:"C"}
roman3 = {1:"C",2:"CC",3:"CCC",4:"CD",5:"D",6:"DC",7:"DCC",8:"DCCC",9:"CM",10:"M"}
roman4 = {1:"M",2:"MM",3:"MMM"}
tho = num//1000 # 只会是0,1,2,3
hun = (num%1000)//100 # 0~9
ten = (num%100)//10 # 0~9
sin = num%10 # 0~9
str_tho = roman4[tho] if tho else ""
str_hun = roman3[hun] if hun else ""
str_ten = roman2[ten] if ten else ""
str_sin = roman1[sin] if sin else ""
return str_tho + str_hun + str_ten + str_sin
我使用了比较好像的罗列法,快速的罗列 还挺快的,最后执行速度和内存都还行
2020 08/12
p1
罗马数字包含以下七种字符: 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 的范围内。 示例 1: 输入: “III” 输出: 3 示例 2: 输入:
“IV” 输出: 4 示例 3: 输入: “IX” 输出: 9 示例 4: 输入: “LVIII” 输出: 58 解释: L = 50,
V= 5, III = 3. 示例 5: 输入: “MCMXCIV” 输出: 1994 解释: M = 1000, CM = 900, XC
= 90, IV = 4.
class Solution(object):
def romanToInt(self, s):
"""
:type s: str
:rtype: int
"""
roman = {"I":1,"V":5,"X":10,"L":50,"C":100,"D":500,"M":1000}
i = 0
sum = 0
while i < len(s):
if i+1 < len(s):
if roman[s[i+1]] > roman[s[i]]:
sum = sum + roman[s[i+1]] - roman[s[i]]
i = i + 2
else:
sum = sum + roman[s[i]]
i = i + 1
else:
sum = sum + roman[s[i]]
i = i + 1
return sum
本质思想:小的在左边肯定是减法,小的在右边就是加法。做个映射 最后相加就行了。
p2
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。
示例 1:
输入: [“flower”,“flow”,“flight”] 输出: “fl” 示例 2:
输入: [“dog”,“racecar”,“car”] 输出: “” 解释: 输入不存在公共前缀。 说明:
所有输入只包含小写字母 a-z 。
class Solution(object):
def longestCommonPrefix(self, strs):
"""
:type strs: List[str]
:rtype: str
"""
max_str = ""
flag = True
if len(strs)>1:
for i in range(len(strs[0])):
for j in range(len(strs)-1):
print(j)
if i< len(strs[j+1]) and strs[j+1][i] == strs[0][i]:
if j == len(strs[1:])-1:
max_str = max_str + strs[j+1][i]
else:
continue
else:
flag = False
break
if not flag:
break
return max_str
else:
if len(strs) == 1:
return strs[0]
else:
return ""
这里用了暴力解法,速度很慢,只有6%,内存还行85%,去看了看大神的解法:
class Solution(object):
def longestCommonPrefix(self, strs):
"""
:type strs: List[str]
:rtype: str
"""
if strs:
count = 0
for temp in zip(*strs): # 编程每个对应位置构成一个列表,取最短的,最后拼成一个大列表
if len(set(temp)) == 1:
count = count + 1
else:
break
max_str = strs[0][:count]
return max_str
else:
return ""
骚操作,利用python的zip函数,将列表迭代成对应位置放一起的列表,最后再放到一起成一个大列表。时间50%。
2020 08/13
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0
?请你找出所有满足条件且不重复的三元组。注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ]
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
results = []
nums.sort()
print(nums)
if len(nums) < 3 or nums[0] > 0 or nums[-1] < 0:
return []
else:
for i in range(len(nums) - 2):
left = i + 1
right = len(nums) - 1 # 右指针初始化为最后一个
if nums[i] > 0:
break
if i > 0 and nums[i] == nums[i - 1]: # 和前面的一样就不再走下去直接开启下一个循环
continue
while left < right and nums[i] <= 0:
if nums[i] + nums[left] + nums[right] == 0:
result = []
result.append(nums[i])
result.append(nums[left])
result.append(nums[right])
results.append(result)
while left < right and nums[left] == nums[left+1]:
left = left + 1
while left < right and nums[right] == nums[right-1]:
right = right - 1
left = left + 1
right = right - 1
elif nums[i] + nums[left] + nums[right] < 0:
left = left + 1
else:
right = right - 1
return results
首先进行排序,然后利用双指针遍历,第一个数一定是小于0,他大于零,后面肯定不可能相加为0,最右边的肯定也不能小于零,否则也没有。
这就确定了截至条件,然后难点还有去重以及,第二个数的移动。
第二个数也就是left(第一个是i),对于去重,跳过相同的,左右都这么干,最后左右都往前走一步。