编程小白用Python刷LeetCode学习笔记
编程小白刚学完Python的基本语法,开始试着用Python刷LeetCode,连最简单的题目都是看答案的,很心酸,不过不管能不能提高编程能力,至少可以学点算法知识吧,希望能坚持。记录一下答案。
1.两数之和
给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。
你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
解:
class Solution:
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
d = {}
for i, n in enumerate(nums):
m = target - n
if m in d:
return [d[m], i]
else:
d[n] = i
7.反转整数
给定一个 32 位有符号整数,将整数中的数字进行反转。
示例 1:
输入: 123
输出: 321
示例 2:
输入: -123
输出: -321
示例 3:
输入: 120
输出: 21
注意:
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231 − 1]。根据这个假设,如果反转后的整数溢出,则返回 0。
解:
class Solution:
def reverse(self, x):
"""
:type x: int
:rtype: int
"""
tmp=abs(x)
sum=0
while tmp>0:
sum=sum*10+tmp%10
tmp=tmp//10
if x<0:
sum=-sum
if sum<2**31 and sum>-2**31:
return sum
else:
return 0
9.回文数
这道题自己尝试写了一下,把数字转换成字符串放在列表里再比较反转前后两个列表是否相同,提交后速度确实不快,只击败33%左右的答案,看了下别人写的最优解,速度一下子就提高了很多。非常弱了,但是至少自己尝试着写出一个解了,菜鸟暗自开心一下下,虽然题目真的超简单,其实本科学C的时候就写过了,然而并没有记住。
自己写的解:
class Solution:
def isPalindrome(self, x):
"""
:type x: int
:rtype: bool
"""
strs=list(str(x))
tmp=[]
for value in strs:
tmp.insert(0,value)
return strs==tmp
偷偷看的最优解:
class Solution:
def isPalindrome(self, x):
"""
:type x: int
:rtype: bool
"""
if x<0:
return False
high=1
while x/high>=10:
high*=10
while x//high==x%10:
x=x%high//10
high=high/100
if high<1:
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
13.罗马数字转整数
例如, 罗马数字 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:
def romanToInt(self, s):
"""
:type s: str
:rtype: int
"""
rom_map={'I':1,
'V':5,
'X':10,
'L':50,
'C':100,
'D':500,
'M':1000}
last_num=None
result=0
for char in s:
curent_num=rom_map[char]
if last_num is None or last_num>=curent_num:
result+=curent_num
elif last_num<curent_num:
result+=curent_num-2*last_num
last_num=curent_num
return result
解法二:
class Solution(object):
def romanToInt(self, s):
"""
:type s: str
:rtype: int
"""
sum=0
convert={'M': 1000,'D': 500 ,'C': 100,'L': 50,'X': 10,'V': 5,'I': 1}
for i in range(len(s)-1):
#if (s[i]=='I' or s[i]=='X' or s[i]=='C') and convert[s[i]]<convert[s[i+1]]:
if convert[s[i]]<convert[s[i+1]]:
sum=sum-convert[s[i]]
else:
sum=sum+convert[s[i]]
return sum+convert[s[-1]]
14.最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。
示例 1:
输入: [“flower”,“flow”,“flight”]
输出: “fl”
示例 2:
输入: [“dog”,“racecar”,“car”]
输出: “”
解释: 输入不存在公共前缀。
说明:
所有输入只包含小写字母 a-z 。
解:
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,c in enumerate(s1):
if c != s2[i]:
return s1[:i]
return s1
20.有效的括号
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
示例 1:
输入: “()”
输出: true
示例 2:
输入: “()[]{}”
输出: true
示例 3:
输入: “(]”
输出: false
示例 4:
输入: “([)]”
输出: false
示例 5:
输入: “{[]}”
输出: true
解:
class Solution:
def isValid(self, s):
"""
:type s: str
:rtype: bool
"""
top_element=''
stack=[]
mapping={')':'(',']':'[','}':'{'}
for char in s:
if char in mapping:
if stack:
top_element=stack.pop()
else:
'#'
if mapping[char]!=top_element:
return False
else:
stack.append(char)
return not stack
21.合并两个有序链表
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
if l1==None:
return l2
if l2==None:
return l1
if l1.val<=l2.val:
ret=l1
ret.next = self.mergeTwoLists(l1.next, l2)
else:
ret=l2
ret.next = self.mergeTwoLists(l1, l2.next)
return ret
26.删除排序数组中的重复项
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 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]);
}
解:
class Solution(object):
def removeDuplicates(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
pos=0
this_num=None
for num in nums:
if num!=this_num:
nums[pos]=num
this_num=num
pos+=1
return pos
35.搜索插入位置
我自己写的穷举法:
class Solution:
def searchInsert(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
if nums[0]>target:
return 0
if nums[-1]<target:
return len(nums)
for i in range(len(nums)):
if nums[i]==target:
return i
elif nums[i]<target and nums[i+1]>target:
return i+1
一般遇到有序数组都应该想到用二分法,下面是一个用二分法的递归函数:
class Solution:
def searchInsert(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
def bs(numlsit, l, r):
while l <= r:
mid = int((l + r) / 2)
if numlsit[mid] == target:
return mid
elif numlsit[mid] < target:
return bs(numlsit, mid+1, r)
else:
return bs(numlsit, l, mid-1)
return l
return bs(nums, 0, len(nums)-1)
53.最大子序和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
解:
class Solution:
def maxSubArray(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
sums=0
maxsum=nums[0]
for value in nums:
sums=sums+value
if maxsum<sums:
maxsum=sums
if sums<0:
sums=0
return maxsum
解法二:
class Solution:
def maxSubArray(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
length=len(nums)
for i in range(1,length):
#当前值的大小与前面的值之和比较,若当前值更大,则取当前值,舍弃前面的值之和
subMaxSum=max(nums[i]+nums[i-1],nums[i])
nums[i]=subMaxSum#将当前和最大的赋给nums[i],新的nums存储的为和值
return max(nums)
58.最后一个单词长度
给定一个仅包含大小写字母和空格 ’ ’ 的字符串,返回其最后一个单词的长度。
如果不存在最后一个单词,请返回 0 。
说明:一个单词是指由字母组成,但不包含任何空格的字符串。
解:
class Solution:
def lengthOfLastWord(self, s):
"""
:type s: str
:rtype: int
"""
str = ''
count = 0
for i in s[::-1]:
if str != '' and i==' ':
return count
if i != ' ':
count = count+ 1
str = str + i
return count
66.加一
给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储一个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。
示例 1:
输入: [1,2,3]
输出: [1,2,4]
解释: 输入数组表示数字 123。
示例 2:
输入: [4,3,2,1]
输出: [4,3,2,2]
解释: 输入数组表示数字 4321。
我自己写的解法:先把列表还原成数然后加一再换回列表
class Solution:
def plusOne(self, digits):
"""
:type digits: List[int]
:rtype: List[int]
"""
num=0
for value in digits:
num=num*10+value
num=num+1
new_list=[None]*len(str(num))
i=len(str(num))-1
while num>0:
new_list[i]=num%10
num=num//10
i-=1
return new_list
别人的直接解法:
class Solution(object):
def plusOne(self, digits):
"""
:type digits: List[int]
:rtype: List[int]
"""
carry = 1
for i in reversed(range(0, len(digits))):
digit = (digits[i] + carry) % 10
carry = 1 if digit < digits[i] else 0
digits[i] = digit
if carry == 1:
return [1] + digits
return digits
69.x的平方根
实现 int sqrt(int x) 函数。
计算并返回 x 的平方根,其中 x 是非负整数。
由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
示例 1:
输入: 4
输出: 2
示例 2:
输入: 8
输出: 2
说明: 8 的平方根是 2.82842…,
由于返回类型是整数,小数部分将被舍去。
解法一:
我的想法是用牛顿迭代法求:
class Solution:
def mySqrt(self, x):
"""
:type x: int
:rtype: int
"""
y=1
lasty=2
while y-lasty>=1 or lasty-y>=1:
lasty=y
y=(lasty+x/lasty)/2
return int(y)
解法二:二分法
class Solution:
def mySqrt(self, x):
left=0;right=x
while left<right:
mid=int((left+right)/2)
if x<mid**2:
right=mid
else:
left=mid+1
if left>1:
return left-1
else:
return left
70.爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
- 1 阶 + 1 阶
- 2 阶
示例 2:
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
3. 1 阶 + 1 阶 + 1 阶
4. 1 阶 + 2 阶
5. 2 阶 + 1 阶
**注意:**此时相当于求斐波那契数列的第n个数
class Solution(object):
def climbStairs(self, n):
"""
:type n: int
:rtype: int
"""
if n<=2:
return n
a=[0]*(n+1)
a[1]=1
a[2]=2
for i in range(3,n+1):
a[i]=a[i-1]+a[i-2]
return a[n]
88.合并两个有序数组
给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。
说明:
初始化 nums1 和 nums2 的元素数量分别为 m 和 n。
你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。
示例:
输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3
输出: [1,2,2,3,5,6]
我的解法:
class Solution:
def merge(self, nums1, m, nums2, n):
"""
:type nums1: List[int]
:type m: int
:type nums2: List[int]
:type n: int
:rtype: void Do not return anything, modify nums1 in-place instead.
"""
num=nums1[:m]+nums2
for i in range(m+n):
value=min(num)
nums1[i]=value
num.remove(value)
别人的解法,我真是想不到。。。
class Solution:
def merge(self, nums1, m, nums2, n):
"""
:type nums1: List[int]
:type m: int
:type nums2: List[int]
:type n: int
:rtype: void Do not return anything, modify nums1 in-place instead.
"""
while m>0 and n>0:
if nums1[m-1]>=nums2[n-1]:
nums1[m+n-1]=nums1[m-1]
m-=1
else:
nums1[m+n-1]=nums2[n-1]
n-=1
if n>0:
nums1[:n]=nums2[:n]