leetcode
备注:红色表示需要重点再刷的
第二遍的时候用Notebook重刷
1)思路一:当前两值和上一轮的进位相加得sum_temp,创建sum_temp % 10新节点,并保存进位数:sum_temp // 10,误忘判断最后一轮是否存在进位
# 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
"""
current = head = ListNode(0)
flag = 0
while (l1 or l2):
x= l1.val if l1 else 0
y= l2.val if l2 else 0
sum_temp = x + y + flag
flag = sum_temp // 10
current.next = ListNode(sum_temp % 10)
current = current.next
if l1:
l1 = l1.next
if l2:
l2 = l2.next
if flag == 1:
current.next = ListNode(1)
return head.next
4. 寻找两个有序数组的中位数
1)思路一:将两个数组进行合并后排序,然后判断合并后的长度的奇偶性,求出中位数(这方法明显不是题目需要的)
2)思路二:待研究
5.最长回文子串
1)思路一:暴露法,两个循环,时间超时
2)思路二:
1)思路一:设置一个变量pre保存前一个字符,遍历第一个字符到最后一个字符,如果pre + cur在字典中,则说明是特殊字符
class Solution(object):
def romanToInt(self, s):
"""
:type s: str
:rtype: int
"""
dict_ = {'temp':0,'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000, 'IV':4, 'IX':9, 'XL':40, 'XC':90, 'CD':400, 'CM':900}
if not s:
return 0
if len(s) == 1:
return dict_[s]
if len(s) == 2:
if s in dict_:
return dict_[s]
else:
return dict_[s[0]] + dict_[s[1]]
else:
result = 0
pre = s[0]
for cur in s[1:]:
if (pre + cur) in dict_:
result += dict_[pre + cur]
pre = 'temp'
else:
result += ( dict_[pre] )
pre = cur
if pre != 'temp':
result += ( dict_[pre] )
return result
17. 电话号码的字母组合
1)思路一:递归,将字符串进行首位和其他位拆分,首位的每个字符和其他位字符分别相加
1)思路一:获取val的个数count,然后执行count次remove
2)思路二:用下标i
class Solution(object):
def removeElement(self, nums, val):
"""
:type nums: List[int]
:type val: int
:rtype: int
"""
i = 0
for x in nums:
if x != val:
nums[i] = x
i = i+1
return i
1)思路一:遍历,但是较慢,但排在前面的算法就是这种遍历方法
2)思路二:待研究其速度,对某些例子可能快点
class Solution(object):
def searchInsert(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
if len(nums) == 0:
return 0
i, j = 0, len(nums)-1
p = (i + j) / 2
while i <= j:
p = (i + j) / 2
if nums[p] == target:
return p
elif nums[p] > target:
j = p - 1
else:
i = p + 1
if nums[p] >= target:
return p
else:
return p+1
1)思路一:直接调用itertools.permutations()函数
2)思路二:递归,再研究
1)思路一:直接调用itertools.permutations()函数,然后用set()去重
1)思路一:先翻转,后调整
class Solution:
def rotate(self, matrix):
"""
Do not return anything, modify matrix in-place instead.
"""
n = len(matrix)
matrix[:] = matrix[::-1]
#print(matrix)
for i in range(0, n):
for j in range(i+1, n):
#print(i, j)
matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
1)思路一:将每个字符串sort后作为Key,每个字符串作为value存入dict()
50. Pow(x, n)
1)思路一:用递归,如果n为奇数,则返回x * Pow(x*x, n / 2),n如果为偶数,直接返回Pow(x*x, n / 2)
1)思路一:max_idx记录每次能达到的最大位置,如果能达到就return True,每次更新最大可达位置
1)思路一:递归,判断p和q空值情况,非空的话判断p.val和q.val是否相等
1)思路一:递归,当前节点不为0的话,深度为1,节点不存在深度为0
107.二叉树的层次遍历II
1)思路一:可以参考429.N叉树的层次遍历,但是竟然超出时间限制
2)思路二:用两个列表分别保存当前节点及其子节点,一轮循环后子节点作为根节点继续遍历
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def levelOrderBottom(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
if not root:
return []
q1 = [root]
result = []
while len(q1):
q2 = []
sub = []
for each in q1:
sub.append( each.val )
if each.left:
q2.append(each.left)
if each.right:
q2.append(each.right)
result.append(sub)
q1 = q2
return result[::-1]
1)思路一:从第三行开始,每一行是上一行的相邻元素相加,首尾都是1
1)思路一:同上
2)思路二:能一个循环吗?
121.买卖股票的最佳时机(曾是百度面试题)
1)思路一:暴力法,遍历前n-1个元素,对于每个元素,获取该元素之后的元素与该元素的最大差值,最后返回最大差值,但是不幸,超出时间限制
#暴力法,也是自己最初想到的方法,max_保存当前最大值,对于当前值,遍历他之后的每一个值,求差值,大于当前最大值,则max_改变
class Solution:
def maxProfit(self, prices):
"""
:type prices: List[int]
:rtype: int
"""
max_ = 0
for i in range(len(prices)-1):
for j in range(i+1, len(prices)):
if(prices[j] - prices[i]) > max_:
max_ = prices[j] - prices[i]
return max_
2)思路二:遍历元素,并保存当前最小价格和最大利润
class Solution:
def maxProfit(self, prices):
"""
:type prices: List[int]
:rtype: int
"""
if not prices:
return 0
minprice = prices[0]
maxprofit = 0
for each in prices:
if each < minprice:
minprice = each
elif each - minprice > maxprofit:
maxprofit = each - minprice
return maxprofit
160. 相交链表
1)思路一:如果是单纯的判断是否相交,那么只需要两个链表的最后一个元素是否相等
2)思路二:如果需要找到相交的节点,那么请看下面的代码
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def getIntersectionNode(self, headA, headB):
"""
:type head1, head1: ListNode
:rtype: ListNode
"""
lenA, lenB = 0, 0
pA = headA
pB = headB
while pA:
pA = pA.next
lenA += 1
while pB:
pB = pB.next
lenB += 1
pA = headA
pB = headB
if lenA > lenB:
for i in range(lenA-lenB):
pA = pA.next
else:
for i in range(lenB-lenA):
pB = pB.next
while pA!=pB:
pA = pA.next
pB = pB.next
return pA
1)思路一:sql题,请参考
select Email from Person group by Email having count(Email) > 1;
1)思路一:bin转换成二进制后利用count
2)思路二:利用n & (n-1)可以消去1个1
1)思路一:递归,先判断0-10返回真还是假,如n == 1或者7时返回真
class Solution:
def isHappy(self, n):
"""
:type n: int
:rtype: bool
"""
if n==1:
return True
if n==0:
return False
if n==7:
return True
if n<10:
return False
num=str(n)
res=0
for nn in num:
res+=int(nn)*int(nn)
print(res)
if res==1:
return True
else:
return self.isHappy(res)
1)思路一:ncpcn
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
prev = None
curr = head
while curr:
next = curr.next
curr.next = prev
prev = curr
curr = next
return prev
1)思路一:
1)思路一:真SB的题,直接给的node就是要删除的节点,并且还不在尾部
1)思路一:将两个字符串进行排序,然后比较是否相等(sorted()应用于字符串,则返回排序列表)
2)思路二:对于非重复字符,判断在两个字符串中的个数是否相等
1)思路一:逐个判断,较慢
2)思路二:利用等差数列和的公式,首项+末项,然后乘以项数,再除以2,这是理论之和,减去目前之和就可得缺少的数字
1)思路一:你要想赢,到你摸的时候必须剩下四个石头
347. 前K个高频元素
1)思路一:哈希保存每个元素频数,然后取前K个
class Solution(object):
def topKFrequent(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
dict_num = {}
for each in nums:
if each not in dict_num:
dict_num[each] = 0
else:
dict_num[each] += 1
return [each[0] for each in sorted(dict_num.items(), key=lambda m: m[1], reverse=True)[0:k]]
1)思路一:遍历小的,看是否在大数组里
2)思路二:利用set
return list(set(nums1) & set(nums2))
1)思路一:合并两个字符串,然后将每个字符转换成数字,后求异或运算
2)思路二:26个字符遍历,如果某个字符在字符串A和B中的数目不同,则返回该字符
1)思路一:注意上面的Led没有12及以上数字,分钟不会超过59
class Solution(object):
def readBinaryWatch(self, num):
"""
:type num: int
:rtype: List[str]
"""
import itertools
result = []
if num == 0:
return ['0:00']
base = ["1:00", "2:00", "4:00", "8:00", "0:01", "0:02", "0:04", "0:08", "0:16", "0:32"]
for x in itertools.combinations(base, num):
hour = 0
mins = 0
for y in x:
hour_temp, mins_temp = y.split(':')
hour += int(hour_temp)
mins += int(mins_temp)
if mins >= 60:
continue
if mins < 10:
mins = '0' + str(mins)
if hour >= 12:
continue
result.append(str(hour) + ':' + str(mins))
return result
412. Fizz Buzz
1)思路一:简单不多说,但注意需要先判断是否是15的倍数
我们先来复习一下python中list的出队操作,pop(index=-1)函数默认出队最后一个元素,index参数指定了要出队的元素下标,出队并返回该元素值,代码示例:
mylist = [4, 5, 2, 1] mylist.pop() #output:1 mylist #output:[4, 5, 2],因为出队一个元素1,所以剩下三个元素 mylist.pop(0) #output:4,出队第一个元素 mylist #output:[5, 2],出队第一个元素4后,只剩下两个元素
1)思路一:利用队列
定义一个列表:\(que = []\),作为保存节点的队列,初始时先将root放在\(que\)中:\(que.append(root)\)
树的层序遍历应该使用队列的迭代法,队列不为空时,出队列元素,把此元素的子结点加入队列
本题需要返回每一层的节点值,因此每次迭代需要遍历一层的节点,于是需要设置变量保存当前队列的长度,然后把这些元素全部拿出队列遍历
"""
# Definition for a Node.
class Node(object):
def __init__(self, val, children):
self.val = val
self.children = children
"""
class Solution(object):
def levelOrder(self, root):
"""
:type root: Node
:rtype: List[List[int]]
"""
if not root:
return []
que = [] # 保存节点的队列
res = [] # 保存结果的列表
que.append(root)# 初始先将 根元素入队列
while len(que): # 判断队列不为空,执行迭代
l = len(que)# 当前层节点数量
sub = [] # 保存每层的节点的值
for i in range(l): #遍历当前层的每个节点,并执行下面的出队操作
current = que.pop(0) # 出队列的当前节点
sub.append(current.val)
for child in current.children: # 所有子结点入队列,会改变que的长度,所以在迭代的时候需要保存当前层的节点数量
que.append(child)
res.append(sub) # 把每层的节点的值加入结果列表
return res
1)思路一:每次操作n-1个元素加1,直到所有元素都相等 == 每次操作最大值-1,直到所有元素等于最小值 == 求所有元素与最小值差值的和
class Solution(object):
def minMoves(self, nums):
sum = 0
minmum = min(nums)
for i in nums:
sum += i-minmum
return sum
#或者
class Solution(object):
def minMoves(self, nums):
return sum(nums) - min(nums)*len(nums)
1)思路一:用异或运算,统计结果中1的数目
1)思路一:待研究
1)思路一:用变量max_1保存当前最大连续1数目,用num保存当前连续1数目,遇到0后判断num是否大于max_1,别忘了最后没遇到0时要判断num和max_1谁大,很不幸,才超过0.77%的人
2)思路二:直接用列表保存每个连续1的个数,最后用max(list)来判断最大值,很不幸,才超过0.77%的人
上面的两个方法应该没问题,尤其第二个方法,自己是参考速度靠前的人的方法,结果还是这么慢,这个是平台的原因
1)思路一:isupper()和islower()的使用
1)思路一:主要判断字串a和b是否相等,相等返回-1,不等的话,返回的是长字串的长度
1)思路一:就看字符串长度有几个2K了
class Solution:
def reverseStr(self, s, k):
return ''.join([s[i: i + k][::-1] + s[i + k: i + 2 * k] for i in range(0, len(s), 2 * k)])
1)思路一:主要比较糖果种类数目和数组长度的一半大小
1)思路一:递归,先用列表保存root.val,遍历子节点,调用自身
1)思路一:合并过程中,如果一个节点为空,则返回另外一个节点;如果要合并的两个节点均不为空,则将一个节点的val加到另外一个节点上,再对两个节点的左右子树执行相同的操作
1)思路一:参考107思路二
1)思路一:用列表保存每一轮的得分,最后求sum
1)思路一:求出该整数对应的二进制字符串的长度N,然后下标\(i\)从\(1\)到\(N-1\)遍历,分别比较\(i-1\)和\(i\)及\(i+1\)是否相等,这里注意N的长度要大于等于3,所以对于整数0,1,2,3来说需要单独判断
2)思路二:求出该整数对应的二进制字符串,直接判断"00" 或者"11"是否存在于字符串中
697. 数组的度
1)思路一:获取频数字典,key为每个元素,value为索引列表,然后求索引列表的最大长度(即最大频数),最后求最大频数列表的索引值的最大跨度
class Solution(object):
def findShortestSubArray(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
dict_temp = {}
for index, value in enumerate(nums):
if value not in dict_temp:
dict_temp[value] = [index]
else:
dict_temp[value].append(index)
length = 0
max_current = 0
for key, value in dict_temp.items():
length_temp = len(value)
if length_temp > length: # 当前key的频数最大
length = length_temp
max_current = value[-1] - value[0] + 1
elif length_temp == length: # 当前key的频数和上一个最大频数相同,即存在相同的频数
if value[-1] - value[0] + 1 < max_current:
max_current = value[-1] - value[0] + 1
else:
continue
else:
continue
return max_current
1)思路一:也是本人的解法,先把字母挑出来后,遍历每个单词,如果每个字母都在该单词中,则保留该单词,最后对单词列表排序
class Solution(object):
def shortestCompletingWord(self, licensePlate, words):
"""
:type licensePlate: str
:type words: List[str]
:rtype: str
"""
licensePlate = licensePlate.lower()
license = ''
for each in licensePlate:
if ord(each) >= 97 and ord(each) < 123 :
license += each
result = []
for each in words:
flag = False
for i in license:
if i not in each or license.count(i) > each.count(i):
flag = True
if flag:
continue
else:
result.append(each)
if not result:
return ''
else:
return sorted(result, key=lambda x: len(x))[0]
2)思路二:参考别人的,感觉不错,更简洁,注意isalpha()的使用
class Solution(object):
def shortestCompletingWord(self, licensePlate, words):
"""
:type licensePlate: str
:type words: List[str]
:rtype: str
"""
l = []
for i in licensePlate:
if i.isalpha():
l.append(i.lower())
for word in sorted(words, key = len):
temp = l[:]
for j in word:
if j in temp:
temp.remove(j)
if len(temp) == 0:
return word
1)思路一:重点记一下
class Solution:
def letterCasePermutation(self, S):
if not S:
return ['']
res, tmp = [''], []
for ch in S:
if '0' <= ch <= '9':
for item in res:
tmp.append(item + ch)
else:
for item in res:
tmp.append(item + ch.lower())
tmp.append(item + ch.upper())
res, tmp = tmp, []
return res
1)思路一:首先用一个字典保存每个字符的宽度,初始化当前line和width,遍历字符串S,width累加每个字符宽度,然后判断累加宽度与100的关系:<100,==100,还是>100?
1)思路一:
1)思路一:无非是判断手里5和10的个数
1)思路一:空格连接两个字符串后,分割,然后只出现一次的单词
1)思路一:sumA - x + y = sumB - y + x
1)思路一:压根没有思路,不知道题目什么意思,待研究
1)思路一:从下标1开始到最后计算后面比前面大还是小,用列表保存每次比较,然后set(list),求集合长度
1)思路一:
数组A中的最小值加上K之后的范围应该是:\([min(A)-K,min(A)+K]\)
数组A中的最大值加上K之后的范围应该是:\([max(A)-K,max(A)+K]\)
那么这两个范围是否有交集呢?也就是说我们来判断一下\(res = max{A}-K - min(A)-K\),如果res > 0,则他们没有有交集,否则他们有交集

浙公网安备 33010602011771号