- 第2题(中等): Add Two Numbers 两数相加
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字0之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
代码:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def addTwoNumbers(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
dummy = ListNode(0)
p = dummy
carry = 0 # 进位
while l1 and l2:
p.next = ListNode((l1.val + l2.val + carry)%10)
carry = (l1.val + l2.val + carry) // 10
l1 = l1.next
l2 = l2.next
p = p.next
if l1:
while l1:
p.next = ListNode((l1.val+carry)%10)
carry = (l1.val+carry) // 10
l1 = l1.next
p = p.next
if l2:
while l2:
p.next = ListNode((l2.val+carry)%10)
carry = (l2.val+carry) // 10
l2 = l2.next
p = p.next
if carry == 1:
p.next = ListNode(1)
p = p.next
return dummy.next
- 第3题(中等):Longest Substring Without Repeating Characters 无重复字符的最长字串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
(1) 示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
(2) 示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
(3) 示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
class Solution(object):
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
start = 0
dict = {} #键为字母,值为索引值
longest = 0
for i in range(len(s)):
if s[i] in dict and dict[s[i]] >= start:
start = dict[s[i]] + 1
dict[s[i]] = i
longest = max(longest,i-start+1)
return longest
- 第5题(中等):Longest Palindromic Substring 最长回文字串
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
示例 2:
输入: “cbbd”
输出: “bb”
思路:根据所给例子可知,有两种情况。
(1) 中心对称:奇数相同,中心一个字母,两边相同
(2) 轴对称:偶数相同,例如bb,bbbb
class Solution(object):
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
palindrome = ""
for i in range(len(s)):
len1 = len(self.getlongestPalindrome(s,i,i))
if len1 > len(palindrome):
palindrome = self.getlongestPalindrome(s,i,i)
len2 = len(self.getlongestPalindrome(s,i,i+1))
if len2 > len(palindrome):
palindrome = self.getlongestPalindrome(s,i,i+1)
return palindrome
def getlongestPalindrome(self,s,l,r):
while l >= 0 and r <= len(s)-1 and s[l] == s[r]:
l -= 1
r += 1
return s[l+1:r]
- 第8题(中等):String to Integer 字符串转整数
题目说明:
请你来实现一个 atoi 函数,使其能将字符串转换成整数。
首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。
当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。
该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。
注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。
在任何情况下,若函数不能进行有效的转换时,请返回 0。
说明:
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231 − 1]。如果数值超过可表示的范围,则返回
INT_MAX (2^31 − 1) 或 INT_MIN (−231) 。
(1)示例 1:
输入: "42"
输出: 42
(2)示例 2:
输入: " -42"
输出: -42
解释: 第一个非空白字符为 '-', 它是一个负号。
我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。
(3)示例 3:
输入: "4193 with words"
输出: 4193
解释: 转换截止于数字 '3' ,因为它的下一个字符不为数字。
(4)示例 4:
输入: "words and 987"
输出: 0
解释: 第一个非空字符是 'w', 但它不是数字或正、负号。
因此无法执行有效的转换。
(5)示例 5:
输入: "-91283472332"
输出: -2147483648
解释: 数字 "-91283472332" 超过 32 位有符号整数范围。
因此返回 INT_MIN (−231) 。
有两种解法:
解法一:
class Solution(object):
def myAtoi(self, str):
"""
:type str: str
:rtype: int
"""
str = str.strip() #去掉前后空格
temp = "" # 暂时存储某一段:只包含一个正负号、或者数字
count = 0 # 记录正负号的个数
flag = False # 标记是否已经执行过数字了
for i in range(len(str)):
if str[i] != "-" and str[i] != "+" and not str[i].isdigit():
# 如果当前字符 不是正号、负号 和数字,则退出循环
break # break语句用在while和for循环中。终止本次循环
else:
if str[i] == "-" or str[i] == "+":
count += 1
if count > 1 or flag:
# 如果正负号的数目超过1,并且已经记录过数字,则退出循环
break
else:
temp += str[i]
elif str[i].isdigit():
flag = True
temp += str[i]
print(temp)
# 循环完之后得到的结果就是:(1) 一个正号或一个负号 (2)最多包含一个正号或者
负号并且他们在最前面,其他字符是数字 (3)是空字符 (4)全是数字
result = 0
if temp != "":
if "-" in temp or "+" in temp:
if len(temp) > 1:
result = int(temp)
else:
result = int(temp)
if result < -2**31:
result = -2**31
if result > 2**31-1:
result = 2**31-1
return result
思路:首先要将输入的内容进行去空格,然后去掉字符串中非数字非正负号的字符,在保留正负号的选择里,只保留一个并且必须他们是在字符串的最开头。通过count值记录正号或者负号个数,通过flag来标记上一个字符是否是数字,当第一个字符就是正号或者负号的时候,我就把其字符叠加到temp里面,这是count就记录了是一个正号或者负号被记录下来了,继续去循环下一个字符,如果下一个字符再是正号或者负号则会跳出循环并不会再将此字符叠加到temp,如果是数字则进行叠加,并且flag会标记已经记录过数字了,接下来只能是数字才会再次叠加不然就结束了循环。循环完整个输入的字符串之后得到的结果可能是空字符串(因为可能此字符串在去除空格后是非数字非正负号的字符开头的)、仅有一个正号或者负号(例如:++5、+.5、–55–等等这些前面一个正号或负号接着一个正号或负号或非数字字符最后得到的就只剩正号或者负号)、只有一个正号或者负号其余字符是数字、全部字符都是数字
循环完之后得到的字符串,再次进行判断是否含有正号或者负号,当有正号或者负号的时候再判断长度是否大于1确保这个字符串不是单独的一个正号或者负号,这时将字符串转换成整数,如果没有正号或者负号,全部是数字时直接转换成整数,当然是空字符串的话就赋值为0,将字符串转换成整数之后再进行判断是否小于-2的31次方和是否大于2的31次方减1,之后得到最后结果
参考链接:https://blog.csdn.net/weixin_37762923/article/details/83014128
第二种解法:
class Solution5:
def myAtoi(self, str):
return max(min(int(*re.findall('^[\+\-]?\d+', str.lstrip())), 2 ** 31 - 1), -2 ** 31)
说明:
分析:
^ 匹配字符串开头
\+\- 表示加减字符
[] 匹配方括号内的任一个字符,[\+\-]即匹配加号或减号
? 前一个字符可有可无
\d 匹配数字字符0~9
+ 匹配前面的一个或多个
整个pattern = '^[\+\-]?\d+'表示从字符串开始,匹配加号或减号(可以没有),并匹配数字字符0~9,直到匹配结果不是数字字符。
re.findall(pattern, string) 返回string中所有与pattern(正则表达式)不重叠匹配项的列表
*将re.findall返回的列表打散为元素(如res=[1, 3], *res输出为1 3),同样*也用于将元祖、字典、字符串打散
int()将结果转为整型并用max(),min()防止越界,满足题目要求(实际上python中不存在32位int类型,不会有越界的问题)
————————————————
版权声明:参考CSDN博主「爱吃猫的小鱼干」的原创文章,
原文链接:https://blog.csdn.net/BreakingDawn0/article/details/102759572
- 第11题:盛最多水的容器 (container with most water)
给定 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
"""
result = 0
left = 0
right = len(height)-1
while left < right:
water = min(height[left],height[right])*(right-left)
if water > result:
result = water
if height[left] < height[right]:
left += 1
else:
right -=1
return result
- 第46题 Permutations 全排列
给定一个没有重复数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
思想:回溯法。
回溯法思路:对于列表[1,2,3]为例,我们逐个位确定全排列的所有可能。回溯法的原理在于在前n-1位元素确定的情况下,求取n位以后的全排列。本例中,首先固定第0位,就是分别将第0位与它本身及后面各位元素交换,得到3种不同的可能,在固定这一位后,在考虑第1位的可能性,将第1位与它本身及其后元素交换,有两种可能性,当前两位元素确定后,最后一位只有一种可能性。因此一共有6种可能。
将列表的第0位与第0位交换(相当于不变),此时列表变为[1,2,3];
1.1 将列表的第1位与第1位交换(相当于不变),得到列表[1,2,3];
1.2 将列表的第1位与第2位交换,得到列表[1,3,2];
将列表的第0位与第1位交换,得到列表[2,1,3];
2.1 将列表的第1位与第1位交换(相当于不变),得到列表[2,1,3];
2.2 将列表的第1位与第2位交换,得到列表[2,3,1];
将列表的第0位与第2位交换,得到列表[3,2,1];
3.1 将列表的第1位与第1位交换(相当于不变),得到列表[3,2,1];
3.2 将列表的第1位与第2位交换,得到列表[3,1,2]
这里需要注意的是,每次交换元素并回溯寻找后,都要将元素交换回来,保持没有交换前的状态。
参考:玖月晴,链接:https://www.jianshu.com/p/9f8e0f00928c
来源:简书
class Solution(object):
def permute(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
def backtrack(first=0):
if first == len(nums):
output.append(nums[:])
for i in range(first,n):
nums[first],nums[i] = nums[i], nums[first]
backtrack(first+1)
## backtrack
##调用结束之后还需要回溯将交换位置的元素还原,以供其他下降路径使用
nums[first],nums[i] = nums[i], nums[first]
n = len(nums)
output = []
backtrack()
return output
第二种解法:应用python自带的库函数,itertools.permutations
class Solution(object):
def permute(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
from itertools import permutations
return list(permutations(nums))
- 第47题:全排列2
给定一个可包含重复数字的序列,返回所有不重复的全排列。
示例:
输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
思路:跟46题相比,就是要去掉最后结果中的 重复,所以多加了一句,nums not in output
class Solution(object):
def permuteUnique(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
def backtrack(first=0):
if first == len(nums) and nums not in output:
output.append(nums[:])
for i in range(first,n):
nums[first],nums[i] = nums[i], nums[first]
backtrack(first+1)
## backtrack
##调用结束之后还需要回溯将交换位置的元素还原,以供其他下降路径使用
nums[first],nums[i] = nums[i], nums[first]
n = len(nums)
output = []
backtrack()
return output
第二种解法:用到 自带库, 以及set 去重复功能
class Solution(object):
def permuteUnique(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
from itertools import permutations
return list(set(permutations(nums)))
- 第17题:电话号码的字母组合
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:
输入:“23”
输出:[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].
说明:
尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。
解题思想:按例题来说,从2的char中选一个,依次与3的每一个char相结合。反之亦然。
即,先生成一个暂时列表:temp = [“a”,“b”,“c”],再使3中的每一个char,依次与temp中的str相加。
class Solution(object):
def letterCombinations(self, digits):
"""
:type digits: str
:rtype: List[str]
"""
if len(digits) == 0:
return []
look_up = {
2:"abc",
3:"def",
4:"ghi",
5:"jkl",
6:"mno",
7:"pqrs",
8:"tuv",
9:"wxyz"
}
result = [""]
for num in digits:
temp_list = []
for char in look_up[int(num)]:
for str in result:
temp_list.append(str+char)
result = temp_list
return result
- 第15题:3Sum 三数之和
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
思路:
- 先将数组排序。
- 排序后,可以按照TwoSum的思路来解题。怎么解呢?就是可以将num[i]的相反数即-num[i]作为target,然后从i+1到len(num)-1的数组元素中寻找两个数使它们的和为-num[i]就可以了。下标i的范围是从0到len(num)-3。
- 这个过程要注意去重。
- 时间复杂度为O(N^2)。
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
n = len(nums)
nums.sort()
result = []
if len(nums) == 0:
return []
if nums[0] > 0:
return []
if nums[-1] < 0:
return []
for i in range(n-2):
if i ==0 or nums[i] > nums[i-1]:
left = i + 1; right = n-1
while left < right:
if nums[left] + nums[right] == -nums[i]:
result.append([nums[i],nums[left],nums[right]])
left += 1; right -= 1
while left< right and nums[left] == nums[left-1]:
left +=1
while left < right and nums[right] == nums[right+1]:
right -=1
elif nums[left] + nums[right] < -nums[i]:
left += 1
else:
right -= 1
return result
- 第16题: 3Sum Closest 最接近的三数之和
给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.
与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).
class Solution(object):
def threeSumClosest(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
nums.sort()
n = len(nums)
if n == 0 or n < 3:
return []
result = nums[0] + nums[1] + nums[-1] # 先设立一个初始值,后面再更新
for i in range(n-1):
if i >0 and nums[i] == nums[i-1]: # 不需要重复找
continue
left = i+1
right = n-1
while left < right:
val = nums[i] + nums[left] + nums[right]
if abs(val-target) < abs(result-target):
result = val
if val == target:
return target
elif val < target:
left += 1
else:
right -=1
return result
- 第18题:4Sum 四数之和
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
注意:
答案中不可以包含重复的四元组。
示例:
给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。
满足要求的四元组集合为:
[
[-1, 0, 0, 1],
[-2, -1, 1, 2],
[-2, 0, 0, 2]
]
思路:有两种解法。第二种解法运用到,最小值和最大值的思想,能大大提高运行速度。
代码一:
class Solution(object):
def fourSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[List[int]]
"""
# 思路:先将nums数组按照递增排序。然后确定四个数的位置:
# 最左端定第一个数,次左端定第二个数,第三个数从3号位开始,第四个数最右端始。
nums.sort()
n = len(nums)
result= []
for i in range(n-3):
if i >0 and nums[i] == nums[i-1]: # 当两个数一样,最终结果会重复
continue
for j in range(i+1,n-2):
if j > i+1 and nums[j] == nums[j-1]:
continue
left = j+1; right = n-1
while left < right:
val = nums[i] + nums[j] + nums[left] + nums[right]
if val == target:
result.append([nums[i],nums[j],nums[left],nums[right]])
left +=1;
right -= 1
while left < right and nums[left] == nums[left-1]:
left+=1
while left < right and nums[right] == nums[right+1]:
right -=1
elif val < target:
left += 1
else:
right -=1
return result
代码二:运用最小值最大值思想,提高运行速度
class Solution(object):
def fourSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[List[int]]
"""
nums.sort()
n = len(nums)
result = []
if n == 0 or n <4:
return []
for i in range(n-3):
# 当i的值与前面的值相等时,忽略
if i > 0 and nums[i] == nums[i-1]:
continue
# 获取当前最小值,如果当前最小值比target大,说明后面越来越大的值根本没戏
min1 = nums[i] + nums[i+1] + nums[i+2] + nums[i+3]
if min1 > target:
continue
# 获取当前最大值,如果当前最大值比target小,忽略
max1 = nums[i] + nums[n-1] + nums[n-2] + nums[n-3]
if max1 < target:
continue
for j in range(i+1, n-2):
if j > i+1 and nums[j] == nums[j-1]:
continue
left = j + 1
right = n-1
min2 = nums[i] + nums[j] + nums[left] + nums[left+1]
if min2 > target:
continue
max2 = nums[i] + nums[j] + nums[right] + nums[right-1]
if max2 < target:
continue
while left < right:
val = nums[i] + nums[j] + nums[left] + nums[right]
if val == target:
result.append([nums[i],nums[j],nums[left],nums[right]])
left +=1; right -= 1
while left < right and nums[left] == nums[left-1]:
left +=1
while left < right and nums[right] == nums[right+1]:
right -=1
elif val < target:
left +=1
else:
right -=1
return result