题目来源于 https://leetcode-cn.com/
给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。
你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。
示例
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
Python代码:
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
compliments = {}
for i in range(len(nums)):
if nums[i] in compliments:
return [compliments[nums[i]], i]
comp = target - nums[i]
compliments[comp] = i
给定一个 32 位有符号整数,将整数中的数字进行反转。
示例 1:
输入: 123
输出: 321
示例 2:
输入: -123
输出: -321
示例 3:
输入: 120
输出: 21
注意:
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231 − 1]。根据这个假设,如果反转后的整数溢出,则返回 0。
Python代码:
def reverse(self, x):
"""
:type x: int
:rtype: int
"""
cmp=lambda a,b: (a>b)-(a0 else s*rev*(rev<2**31) #处理溢出,并根据s的取值(-1,或1)来确定正负号。
判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
示例1:
输入:121
输出:true
示例2:
输入:-121
输出:false
实例2解释:从左向右读,为-121,从右向左读,为121-,因此不是一个回文数。
示例3:输入10
输出:false
Python代码:
def isPalindrome(x):
s=str(x)
if s[::-1] == s: #翻转后与原字符串比较
return True
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 的范围内。
示例 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.
Python代码:
def romanToInt(s):
rom_to_int = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
result = 0
num = 3999
for i in s:
t = rom_to_int[i]
if t<= num: #通常情况下,罗马数字中小的数字在大的数字的右边
num = t
else:
num = -2*num + t #特殊情况,这种情况的数学定义隐含很深
result += num
return result
'''
总结:
给定任意的罗马数字字符串,理想情况(第i个字符字符代表的值比第i+1的大)都是从左往右依次相加就行(只执行上述中的if)。
但是如果遇到了特殊情况,比如第i个字符代表的数字比第i+1代表的小(出现特殊情况),
那么通过(-2*num+t)就可以让第i+1个字符代表的数字临时改变,使第i、第i+1两个字符组合的罗马数字的值符合6种特殊情况的值(这一点很难想到)
思考:
特殊情况下-2*num+t 为什么能保持num在下一轮的循环里if或else正确?而不会出现num值变大或者变小的情况?
'''
print(romanToInt("M"))
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""
。
示例 1:
输入: ["flower","flow","flight"]
输出: "fl"
示例 2:
输入: ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。
说明:
所有输入只包含小写字母 a-z
。
Python代码:
import itertools
def longestCommonPrefix(strs):
"""
参数:List
返回值: str
"""
prefix = ""
for chars in itertools.zip_longest(*strs):
##chars类型为元组,就像这样('h', 'h', 'h'),通过类型转换来变成set去重
if len(set(chars)) == 1: ##set去重后若等于1,说明存在一个共同字符
prefix += chars[0]
else:
return prefix
print(longestCommonPrefix(["hello","he","hel"]))
'''
**************************************************************
知识点一:
itertools模块: 提供了用于操作迭代对象的一系列函数。
和内置的zip模块功能类似(一一对应),不过zip是以元素最少的对象为准,而zip_longest是以元素最多的对象为标准,使用fillvalue来填充。
example:
res = zip_longest('abc', '12')
for x in res:
print(x)
结果:
('a', '1')
('b', '2')
('c', None)
*****************************************************************
知识点二:
zip_longest的参数*strs。
因为传入的值是一个列表,不能对其直接做zip_longest操作,加*能将列表解开成独立的参数。
就相当于 itertools.zip_longest("hello","he","hel"),这种参数也符合zip_longest参数特征。
'''
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串,判断字符串是否有效。
有效字符串需满足:
注意空字符串可被认为是有效字符串。
示例 1:
输入: "()"
输出: true
示例 2:
输入: "()[]{}"
输出: true
示例 3:
输入: "(]"
输出: false
示例 4:
输入: "([)]"
输出: false
示例 5:
输入: "{[]}"
输出: true
Python代码:
def isValid(s):
"""
:type s: str
:rtype: bool
"""
list=[]
for c in s:
if c == '(':
list.append('(')
elif c == ')':
if not list or list.pop() != '(':
return False
elif c == '[':
list.append('[')
elif c == ']':
if not list or list.pop() != '[':
return False
elif c == '{':
list.append('{')
elif c == '}':
if not list or list.pop() != '{':
return False
if list:
return False
else:
return True
print(isValid("{}()[])"))
'''
*************************************************************
上述实现方法是最直接易懂的,不像算法4有一个骚操作,但很多地方可以改进。
思想:栈结构
1、如果遇到三种任意左括号,则append入栈。
2、如果遇到一种右括号,则判断list是否为空或者list的最后一个元素是否为这种右括号对应的左括号。
因为如果list为空,说明此时来的右括号匹配不到左括号,返回False。如果pop最后的一个元素不为其对
应的左括号,也说明不匹配。
3、如果中间的这些过程都完美匹配了,即for循环里面的return False都没有执行。则在循环结束时判断list是否为空,为空说明每一个左括号的append有其对应的右括号pop,导致list空,返回True。不为空说明list里面至少残留一个左括号没有匹配的右括号。
'''
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
示例 1:
给定数组 nums = [1,1,2], 函数应该返回新的长度 2, 并且原数组nums的前两个元素被修改为1
,2
。 你不需要考虑数组中超出新长度后面的元素。
示例 2:
给定 nums = [0,0,1,1,1,2,2,3,3,4], 函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为0
,1
,2
,3
,4
。 你不需要考虑数组中超出新长度后面的元素。
说明:
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
可以想象内部操作如下:
// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);
// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}
Python代码:
def removeDuplicates( nums):
"""
参数:List
返回值:int
"""
i = 0
if nums:
for j in range(1,len(nums)):
if nums[i] != nums[j]:
nums[i+1], nums[j] = nums[j], nums[i+1] ##python中两个值交换
i = i + 1
print(nums)
return i+1
else:
return 0
print(removeDuplicates([1,2,2,3,4,4,5]))
'''
这个解法觉得还是有点难理解
*****************************************************************
骚操作补充:
如果只考虑返回值的正确性的话,考虑快速将其去重并排序
nums=[1,2,2,3,3,4,5]
print(len(sorted(list(set(nums)))))
print(sorted(list(set(nums))))
输出结果:5
叔叔结果:[1,2,3,4,5]
#先set去重,再list转换成适合sorted的类型,再sorted排序。
'''
给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例 1:
给定 nums = [3,2,2,3], val = 3,
函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。
你不需要考虑数组中超出新长度后面的元素。
示例 2:
给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度5
, 并且 nums 中的前五个元素为0
,1
,3
,0
, 4。 注意这五个元素可为任意顺序。 你不需要考虑数组中超出新长度后面的元素。
Python3代码
def removeElement(nums,val):
'''
:type nums: List[int]
:type val: int
:rtype: int
'''
while val in nums:
nums.remove(val) #因为不需要考虑超出新长度后面的元素,所以可以用用remove使整个list长度变短
return nums
print(removeElement([0,1,2,2,3,0,4,2],2))
'''
**************************************************
总结:
如果使用java之类的语言实现的,我自己首先想到的是把等于val的元素放到后面去。
但是python中的list的remove方法,刚好也能满足条件,而且还不用考虑超出新长度的那些元素,所以等于val的元素在新list中可有可无,而python中刚好是无。
'''
实现 strStr() 函数。
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
示例 1:
输入: haystack = "hello", needle = "ll"
输出: 2
示例 2:
输入: haystack = "aaaaa", needle = "bba"
输出: -1
说明:
当 needle
是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
对于本题而言,当 needle
是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。
Python3代码:
def strStr(h, n):
"""
:type haystack: str
:type needle: str
:rtype: int
"""
if len(n) == 0:
return 0
return int(len(h.split(n)[0])) if len(h.split(n)[0])!=len(h) else -1
print(strStr("aaaaa","ba"))
'''
总结:
通过split,得到的结果是和目标子串不一样的子串列表。
如果第一个子串列表的元素[0]长度刚好等于h的长度,说明整个字符串h没有匹配到分割符n,导致子串列表只有一个元素,即h本身。
如果子串列表的第一个元素长度不等于h的长度,那么一定刚好第一个子串(下标0的元素)的长度就是第一次出现目标子串的下标,即目标返回值。
(split后的列表中,第一个子串长度len=第一个子串最后字符下标值+1=目标(n)的下标)
'''
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
示例 1:
输入: [1,3,5,6], 5
输出: 2
示例 2:
输入: [1,3,5,6], 2
输出: 1
示例 3:
输入: [1,3,5,6], 7
输出: 4
示例 4:
输入: [1,3,5,6], 0
输出: 0
Python3代码:
def searchInsert(nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
for index in range(len(nums)):
if nums[index] >= target:
return index
elif index == len(nums) - 1:
return len(nums)
return 0
print(searchInsert([1,2,3,3,3,4,4,5],3))
'''
******************************8
总结:
从左往右,如果遇到一次nums[index]>=value,说明找到了位置,可以停止循环,刚好插入在index位置,返回index。
如果没遇到nums[index]>=value,说明循环应该继续往右走,并且如果走到末尾位置,即index=len(nums)-1,
说明应该插入在原列表的最后位置,即下标=len(nums)
'''