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
1)思路一:字符串列表从第二号元素开始,判断前面的字符串是否和第一个元素的前几个字符串相等
1)思路一:暴力法,三个循环,超时
2)思路二:固定一个指针,移动另外两个指针
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)思路一:没啥难的
66. 加一
1)思路一:判断最后一位是否是9即可
class Solution(object): def plusOne(self, digits): """ :type digits: List[int] :rtype: List[int] """ length = len(digits) for x in range(length-1, -1, -1): if digits[x] == 9: digits[x] = 0 else: digits[x] += 1 return digits #防止全是9,则第一位应该是1,剩余全为0 return [1] + digits
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
1)思路一:遍历,利用count()函数
2)思路二:利用异或运算,两个相同的数字进行异或运算结果是0,0和任意的数字n进行异或运算结果是n本身
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)思路一:
235. 二叉搜索树的最近公共祖先
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)思路一:先参考二叉搜索树的结构,对二叉搜索树采用右中左的顺序遍历树节点,得到的值就是从大到小排列的。使用一个变量记录节点值的累计和,并将该变量记录的累计和不断赋予给对应的节点
# Definition for a binary tree node. # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution: def convertBST(self, root): """ :type root: TreeNode :rtype: TreeNode """ self.sum_node = 0 def inorder(node): if not node: return None inorder(node.right) self.sum_node += node.val node.val = self.sum_node inorder(node.left) inorder(root) return root
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)思路一:将该二叉搜索树中序遍历,然后用双指针
# 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 findTarget(self, root, k): """ :type root: TreeNode :type k: int :rtype: bool """ self.tmp_list = [] self.order(root) i = 0 j = len( self.tmp_list ) - 1 while i < j: sum_tmp = self.tmp_list[i] + self.tmp_list[j] if sum_tmp == k: return True elif sum_tmp > k: j -= 1 else: i += 1 return False def order(self, node): if not node: return self.order(node.left) self.tmp_list.append(node.val) self.order(node.right)
1)思路一:判断当前root.val是比R大还是比L小,如果比R大,则root.left即为新的root,如果比L小,则root.right即为新的root
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)思路:初读题目可能有点绕,其实就是对字符串J中的每个字符,求在S中的数目和
1)思路一:中序遍历,然后求两两之间最小值
# Definition for a binary tree node. # class TreeNode(object): # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution(object): def minDiffInBST(self, root): """ :type root: TreeNode :rtype: int """ vals = [] def inOrder(root): if not root: return inOrder(root.left) vals.append(root.val) inOrder(root.right) inOrder(root) return min([vals[i+1]-vals[i] for i in range(len(vals)-1)])
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,则他们没有有交集,否则他们有交集
1)思路一:先中序遍历二叉搜索树,将值用列表保存。然后将L和R之间的值相加
# Definition for a binary tree node. # class TreeNode(object): # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution(object): def rangeSumBST(self, root, L, R): """ :type root: TreeNode :type L: int :type R: int :rtype: int """ def dfs(root): if not root: return dfs(root.left) res.append(root.val) dfs(root.right) res=[] dfs(root) total=0 for i in res: if L<=i<=R: total+=i return total
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(object): def __init__(self): self.num=0 def rangeSumBST(self, root, L, R): """ :type root: TreeNode :type L: int :type R: int :rtype: int """ if root==None: return if root.val<L: self.rangeSumBST(root.right,L,R) elif root.val>R: self.rangeSumBST(root.left,L,R) else: self.num+=root.val self.rangeSumBST(root.right,L,R) self.rangeSumBST(root.left,L,R) return self.num
1)思路一:这个比较经典,可以用两个变量保存当前最大值和最小值,如果遇到需要递减,则将追加当前最大值,如果需要递增,则追加当前最小值,别忘最后的追加
1)思路一:先对数组逆序排序,然后从0到倒数第三个遍历,如果当前元素小于后面两个元素的和,就找到了组成三角形的三个长度
977. 有序数组的平方
985. 查询后的偶数和
1)思路一:先把原列表中的偶数相加求和,记为sum,然后每一轮查询先判断待修改的值是偶数还是奇数,如果是偶数,那么sum - 该偶数,后该偶数加上更新值,如果待修改的数是奇数,则直接加上更新值
1)思路一:bin和int函数的使用
1)思路一:用栈,栈空的时候就是去除外层的时候
class Solution(object): def removeOuterParentheses(self, S): """ :type S: str :rtype: str """ result = '' stack = [] temp = '' for each in S: temp += each if each == '(': stack.append(each) else: stack.pop(-1) # 遇到),则出栈(,然后判断栈是否为空 if not stack: result += temp[1:-1] temp = '' return result
1)思路一:利用临时数组(将原数组排序)和原数组相同位置上的元素做比较
1)思路一:太简单,一个replace搞定
1)思路:求每个字符的最少出现次数