思路
x x x和 x + 1 x+1 x+1的二进制在某一位后面的数为相反数,相与后均为0。m,n分别右移一位,抹掉m,n的右边一位时,tail加1,得到m,n相等的前缀,共抹掉tail位,左移tail位补充为0
栗子:
十进制 | 二进制 |
---|---|
5 | 0000 0101 |
6 | 0000 0110 |
& | 0000 0100 |
7 | 0000 0111 |
& | 0000 0100 |
十进制 | 二进制 | m,n,ans | tail |
---|---|---|---|
5>>=1 | 0000 0010 | m=2 | tail=1 |
7>>=1 | 0000 0011 | n=3 | tail=1 |
2>>=1 | 0000 0001 | m=1 | tail=2 |
3>>=1 | 0000 0001 | n=1 | tail=2 |
1<<=2 | 0000 0100 | ans=4 | tail=2 |
class Solution(object):
def rangeBitwiseAnd(self, m, n):
"""
:type m: int
:type n: int
:rtype: int
"""
tail = 0
while m!=n:
m >>= 1
n >>= 1
tail += 1
return m<<tail
思路
计算各位数的平方和是否等于1,不等于1时,查看该平方和是否曾经出现过,曾经出现表示出现循环,返回False。未出现则继续计算;如果平方和等于1则返回True
class Solution(object):
def isHappy(self, n):
"""
:type n: int
:rtype: bool
"""
visited = [n]
while n!=1:
sum_squares = 0
while n!=0:
sum_squares += (n%10)**2
n //=10
n = sum_squares
if sum_squares not in visited:
visited.append(sum_squares)
else:
return False
return True
class Solution(object):
def removeElements(self, head, val):
"""
:type head: ListNode
:type val: int
:rtype: ListNode
"""
if not head:
return head
pre = head
while pre and pre.val == val: # 当第一个结点等于val时移除
pre=pre.next
rehead = pre
cur = pre.next if pre else None
while cur:
if cur.val == val: # 当结点等于val时移除
pre.next = cur.next
cur = pre.next
else:
pre = cur
cur = cur.next
return rehead
思路
哨兵
class Solution(object):
def removeElements(self, head, val):
"""
:type head: ListNode
:type val: int
:rtype: ListNode
"""
pre = ListNode(0) # 哨兵
pre.next = head
rehead, cur = pre, pre.next
while cur:
if cur.val == val:
pre.next = cur.next
cur = pre.next
else:
pre = cur
cur = cur.next
return rehead.next
class Solution(object):
def countPrimes(self, n):
"""
:type n: int
:rtype: int
"""
if n < 2:
return 0
ans = 0
isPrime = [True]*(n+1)
isPrime[0], isPrime[1]=False, False
for i in range(2, n):
if isPrime[i]: # 当i为质数时,将i的倍数置为非质数(False)
ans += 1
for j in range(i+i, n+1, i):
isPrime[j]=False
return ans
class Solution(object):
def isIsomorphic(self, s, t):
"""
:type s: str
:type t: str
:rtype: bool
"""
visited = dict()
n = len(s)
for i in range(n):
if s[i] not in visited: # s[i]未访问过时,添加至visited中
if t[i] in visited.values(): # t[i]已出现在visited的values时,说明已经有映射的字符(对应的s[i]应在visited中),因此返回False
return False
visited[s[i]] = t[i]
else:
if visited[s[i]] != t[i]: # s[i]已访问过,映射的字符与t[i]不相等,返回False
return False
return True
class Solution(object):
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
pre, cur = None, head
while cur!=None:
cur_next = cur.next
cur.next = pre
pre = cur
cur = cur_next
return pre
class Solution(object):
def canFinish(self, numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: bool
"""
edges = collections.defaultdict(list)
indegree = [0]*numCourses
for lesson in prerequisites:
edges[lesson[1]].append(lesson[0]) # 学习lesson[0]前需要学习lesson[1]
indegree[lesson[0]]+= 1 # lesson[0]的入度加1
# 当课程的入度为0时,添加至队列中,即该课程无先修课程
queue = [l for l in range(numCourses) if indegree[l]==0]
learned = 0
while queue:
prerequisite = queue.pop(0) # 取出队列第一个课程
learned += 1 # 可以学习的课程数加1
for cur in edges[prerequisite]: # edges[prerequisite]为cur的先修课程
indegree[cur] -= 1 # cur当前课程的入度减1
if indegree[cur] == 0: # 当前课程入度为0时,添加至队列中
queue.append(cur)
return learned==numCourses # 返回学习的课程数是否等于总课程数
class Trie(object):
def __init__(self):
"""
Initialize your data structure here.
"""
self.root = {"is_end":True}
def insert(self, word):
"""
Inserts a word into the trie.
:type word: str
:rtype: None
"""
node = self.root
# 如word="apple" 得到{'is_end': True, 'a': {'p': {'p': {'l': {'e': {'is_end': True}}}}}}
for c in word:
if c in node.keys(): # 字母存在前缀树中时,node指向改字母
node = node[c]
else: # 字母不存在前缀树中时,添加字母至前缀树中,并将node指向该字母
node[c] = dict()
node = node[c]
node["is_end"] = True
def search(self, word):
"""
Returns if the word is in the trie.
:type word: str
:rtype: bool
"""
node = self.root
for c in word:
if c in node.keys():
node = node[c]
else:
return False
if "is_end" in node.keys(): # word是否存在前缀树中
return True
else:
return False
def startsWith(self, prefix):
"""
Returns if there is any word in the trie that starts with the given prefix.
:type prefix: str
:rtype: bool
"""
node = self.root
for c in prefix:
if c in node.keys():
node = node[c]
else:
return False
return True # prefix存在前缀树中
# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)
思路
双指针:
i指向0,j往右滑动。符合题目要求时,当ans为0时,计算符合要求的子数组长度,ans不为0时,比较原ans和新计算的值取其较小值
class Solution(object):
def minSubArrayLen(self, s, nums):
"""
:type s: int
:type nums: List[int]
:rtype: int
"""
i, ans, sumNums = 0, 0, 0
for j in range(len(nums)):
sumNums += nums[j]
while sumNums>=s:
ans = j-i+1 if ans==0 else min(ans, j-i+1)
sumNums -= nums[i]
i += 1
return ans
class Solution(object):
def findOrder(self, numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: List[int]
"""
edges = collections.defaultdict(list)
indegrees = [0]*numCourses # 每节课的入度
for lesson in prerequisites:
edges[lesson[1]].append(lesson[0])
indegrees[lesson[0]] += 1
queue = [l for l in range(numCourses) if indegrees[l]==0]
learned = list()
while queue:
prerequisite = queue.pop(0)
learned.append(prerequisite)
for cur in edges[prerequisite]:
indegrees[cur] -= 1
if indegrees[cur] == 0:
queue.append(cur)
if len(learned) == numCourses:
return learned
else:
return []
class WordDictionary(object):
def __init__(self):
"""
Initialize your data structure here.
"""
self.root = {"is_end":dict()}
def addWord(self, word):
"""
Adds a word into the data structure.
:type word: str
:rtype: None
"""
node = self.root
for c in word:
if c in node.keys():
node = node[c]
else:
node[c] = dict()
node = node[c]
node["is_end"] = dict()
def search(self, word):
"""
Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter.
:type word: str
:rtype: bool
"""
return self.__search(word, self.root)
def __search(self, word, trie): # 回溯
if not word: # word是否存在前缀树trie中
if "is_end" in trie.keys():
return True
return False
if word[0] == ".": # 当字符为“.”时,对比下一个字符
for c in trie:
if self.__search(word[1:], trie[c]):
return True
elif word[0] in trie.keys(): # 当字符存在trie时,对比下一个字符
if self.__search(word[1:], trie[word[0]]):
return True
return False
# Your WordDictionary object will be instantiated and called as such:
# obj = WordDictionary()
# obj.addWord(word)
# param_2 = obj.search(word)
class Solution(object):
def findWords(self, board, words):
"""
:type board: List[List[str]]
:type words: List[str]
:rtype: List[str]
"""
def search(row, col, trie): # 回溯
curNode = trie[board[row][col]] # 指向trie当前结点
visited.append((row, col)) # 添加已访问的结点
if "is_end" in curNode.keys(): # 指向is_end时,存在该单词,保存在ans中
if curNode["is_end"] not in ans: # 去重
ans.append(curNode["is_end"])
for i, j in [(-1, 0), (1, 0), (0, -1), (0, 1)]: # 上下左右
newRow, newCol = row+i, col+j
if 0 <= newRow < m and 0 <= col + j < n: # 在合法范围内移动
if (newRow, newCol) not in visited: # 在该单词内未访问过的点
if board[newRow][newCol] in curNode.keys(): # 字符匹配
search(newRow, newCol, curNode)
visited.pop()
trie = dict()
for word in words:
node = trie
for c in word:
node = node.setdefault(c, dict())
node["is_end"] = word
ans = list()
m, n = len(board), len(board[0])
for i in range(m): # 遍历board,当board[i][j]出现在trie时,查找对应的单词
for j in range(n):
if board[i][j] in trie:
visited = []
search(i, j, trie)
return ans
class Solution(object):
def rob(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
n = len(nums)
return max(self.__rob(nums[:n-1]), self.__rob(nums[1:n])) if n>1 else nums[0]
def __rob(self, nums):
pre, cur = 0, 0
for num in nums:
# i-2(pre)房屋得到的现金和i房屋相加 与 i-1(cur)(不能与i房屋相加)能得到的现金相比较选择较大值
cur, pre = max(num+pre, cur), cur
return cur
思路
找出s本身最长回文串s[:i],剩下s[i:]为非回文,将s[i:]逆序后拼接在s字符串前即可
栗子:
s = “abcd”
s的最长回文串s[:i]:“a”
s剩下字符为非回文串s[i:]:“bcd”–>“dcb”(逆序)
将s[i:]逆序拼接在s字符串前:“dcbabcd”
class Solution(object):
def shortestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
r = s[::-1]
if r == s:
return s
for i in range(1, len(s)):
if s[:-i] == r[i:]:
return r[:i]+s
class Solution(object):
def findKthLargest(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: int
"""
def quickSort(nums, left, right): # 快排
if left < right:
i, j = left, right
key = nums[i]
while i < j:
while i < j and nums[j] > key:
j -= 1
nums[i] = nums[j]
while i < j and nums[i] <= key:
i += 1
nums[j] = nums[i]
nums[i] = key
quickSort(nums, left, i-1)
quickSort(nums, i+1, right)
quickSort(nums, 0, len(nums)-1)
return nums[-k]
思路
参考 39. 组合总和 和 40. 组合总和 II 回溯
index:[1-9]
sub:[1-9]的子集
sumn:sub子集的和
class Solution(object):
def combinationSum3(self, k, n):
"""
:type k: int
:type n: int
:rtype: List[List[int]]
"""
def solve(index, sub, sumn): # 回溯
if sumn == n and len(sub)==k:
if sub not in ans:
ans.append(sub)
return
if sumn > n or index > 9 or len(sub) > k:
return
if sumn + index <=n:
solve(index+1, sub+[index], sumn+index) # 将index添加至sub中
solve(index+1, sub, sumn)
ans = list()
solve(1, [], 0)
return ans
class Solution(object):
def containsDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
nonrepeat = set()
for num in nums:
if num in nonrepeat:
return True
else:
nonrepeat.add(num)
return False
思路
列表排序:
x.sort(key=lambda x: (x[0], -x[1]))
heapq:是一种优先队列。优先队列让你能够以任意顺序添加对象,并随时(可能是在两次添加对象之间)找出(并删除)最小的元素。它们虽然不是严格排序的,但必须保证一点:位置i处的元素总是大于位置i // 2处的元素(反过来说就是小于位置2 * i和2 * i + 1处的元素)。这是底层堆算法的基础,称为堆特征(heap property)
函数 | 描述 |
---|---|
heappush(heap,x) | 将x压入堆中 |
heappop(heap) | 从堆中弹出最小的元素 |
heapify(heap) | 让列表具备堆特征 |
heapreplace(heap,x) | 弹出最小的元素,并将x压入堆中 |
nlargest(n, iter) | 返回iter中n个最大的元素 |
nsmallest(n, iter) | 返回iter中n个最小的元素 |
import heapq
class Solution(object):
def getSkyline(self, buildings):
"""
:type buildings: List[List[int]]
:rtype: List[List[int]]
"""
x = list()
heights = [0] # 保存当前位置的所有高度
last = [0, 0] # 保存上个位置转折点的横左边和高度
visited = list() # 保存右端点位置的高度
ans =[[0,0]]
for building in buildings:
x.append([building[0], -building[2]]) # 记录左端点,高度为负
x.append([building[1], building[2]]) # 记录右端点,高度为正
x.sort() # 对x列表排序
for point in x:
if point[1] < 0: # 左端点,将高度如入最小堆(最小值始终在第一位)
heapq.heappush(heights, point[1])
else: # 右端点,移除该端点对应的高度
visited.append(point[1])
while visited and -heights[0] in visited:
tmp = -heights[0]
heapq.heappop(heights)
visited.remove(tmp)
maxHeight = -heights[0]
# 转折点:上一个位置的高度不等于当前位置的最高高度,更新last,将last添加至ans中
if last[-1] != maxHeight:
last = [point[0], maxHeight]
# 该位置的横坐标与ans中最后一个转折点的横坐标相同,去除ans中最后一个转折点
if point[0] == ans[-1][0]:
ans.pop()
if not ans:
ans.append(last[:])
# 最高高度与ans中最后一个转折点的高度不相同时,添加至答案中
elif maxHeight != ans[-1][1]:
ans.append(last[:])
if [0, 0] in ans:
return ans[1:]
return ans
class Solution(object):
def containsNearbyDuplicate(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: bool
"""
visited = set()
for i in range(len(nums)):
if nums[i] in visited: # nums[i]存在visited中返回True
return True
else:
visited.add(nums[i]) # nums[i]不存在visited中,添加nums[i]至visited中
if len(visited) > k: # 当visited长度大于k时,弹出nums[i-k]
visited.remove(nums[i-k])
return False # 没有符合条件的重复元素
思路
class Solution(object):
def containsNearbyDuplicate(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: bool
"""
n = len(nums)
if n <= k:
if len(set(nums)) != n: # nums长度小于等于k时存在重复元素
return True
else:
if len(set(nums[n-k:])) != k: # nums倒数k个元素内存在重复元素
return True
for i in range(n-k):
if nums[i] in nums[i+1:i+k+1]: # nums[:n-k]中存在符合条件的重复元素
return True
return False # 没有符合条件的重复元素
class Solution(object):
def containsNearbyAlmostDuplicate(self, nums, k, t):
"""
:type nums: List[int]
:type k: int
:type t: int
:rtype: bool
"""
if k == 10000: # 放弃治疗
return False
visited = set()
for i in range(len(nums)):
for num in visited:
if nums[i]-t <= num <= nums[i] + t:
return True
visited.add(nums[i])
if len(visited) > k:
visited.remove(nums[i-k])
return False
class Solution(object):
def maximalSquare(self, matrix):
"""
:type matrix: List[List[str]]
:rtype: int
"""
if not matrix or not matrix[0]:
return 0
m, n, maxSide = len(matrix), len(matrix[0]), 0
dp = [[0]*n for _ in range(m)]
for r in range(m):
for c in range(n):
if matrix[r][c] == "1": # 遇到1的时候
if r==0 or c==0: # 第一行与第一列
dp[r][c] = 1
else:
# 左方、上方和左上方的最小值加1
dp[r][c] = min(dp[r-1][c], dp[r][c-1], dp[r-1][c-1]) + 1
maxSide = max(maxSide, dp[r][c])
return maxSide*maxSide
class Solution(object):
def countNodes(self, root):
"""
:type root: TreeNode
:rtype: int
"""
def preorder(root):
return 0 if not root else 1 + preorder(root.left) + preorder(root.right)
return preorder(root)
思路
矩形1面积+矩形2面积-相交面积
矩形面积:(A, B)为左下角, (C, D)为右上角,面积为(C-A)*(D-B)
相交面积: w × h w \times h w×h
相交的x坐标宽度w:矩形1和矩形2右上角x坐标较小值min(C, G)减矩形1和矩形2左下角x坐标较大值max(A, E),不相交时为负取0,即 w = m a x ( 0 , m i n ( C , G ) − m a x ( A , E ) ) w=max(0, min(C, G)-max(A, E)) w=max(0,min(C,G)−max(A,E))
相交的y坐标高度h:矩形1和矩形2右上角y坐标较小值min(D, H)减矩形1和矩形2左下角y坐标较大值max(B, F),不相交时为负取0,即 h = m a x ( 0 , m i n ( D , H ) − m a x ( B , F ) ) h=max(0, min(D, H)-max(B, F)) h=max(0,min(D,H)−max(B,F))
class Solution(object):
def computeArea(self, A, B, C, D, E, F, G, H):
"""
:type A: int
:type B: int
:type C: int
:type D: int
:type E: int
:type F: int
:type G: int
:type H: int
:rtype: int
"""
w = max(0, min(C, G)-max(A, E))
h = max(0, min(D, H)-max(B, F))
return (C-A)*(D-B)+(G-E)*(H-F)-w*h
class Solution(object):
def calculate(self, s):
"""
:type s: str
:rtype: int
"""
operand = 0 # 操作数
sign = 1 # 1为正式,0为负数
ans = 0
stack = list()
for c in s:
if c.isdigit(): # 字符为数字,添加至操作数中
operand = operand*10+int(c)
elif c=="+":
ans += sign*operand # ans累加正号前一个数
sign, operand = 1, 0 # 将sign至为1,operand归0
elif c=="-":
ans += sign*operand # ans累加负号前一个数
sign, operand = -1, 0 # 将sign至为-1,operand归0
elif c=="(":
stack.append(ans) # (前得到的运算结果入栈
stack.append(sign) # sign运算符入栈
ans, sign = 0, 1
elif c==")":
ans += sign*operand
ans *=stack.pop() # 运算符sign出栈,为括号前的正负符号
ans += stack.pop()
operand = 0
return ans+sign*operand
class MyStack(object):
def __init__(self):
"""
Initialize your data structure here.
"""
self.a = list()
def push(self, x):
"""
Push element x onto stack.
:type x: int
:rtype: None
"""
self.a.append(x)
def pop(self):
"""
Removes the element on top of the stack and returns that element.
:rtype: int
"""
return self.a.pop()
def top(self):
"""
Get the top element.
:rtype: int
"""
return self.a[-1]
def empty(self):
"""
Returns whether the stack is empty.
:rtype: bool
"""
return not self.a
# Your MyStack object will be instantiated and called as such:
# obj = MyStack()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.top()
# param_4 = obj.empty()
class Solution(object):
def invertTree(self, root):
"""
:type root: TreeNode
:rtype: TreeNode
"""
if not root:
return root
right = self.invertTree(root.left)
left = self.invertTree(root.right)
root.left, root.right = left, right
return root
class Solution(object):
def calculate(self, s):
"""
:type s: str
:rtype: int
"""
operand = 0
sign = "+"
stack = list()
for i in range(len(s)):
if s[i].isdigit():
operand = operand*10+int(s[i])
if s[i] in ["+", "-", "*", "/"] or i == len(s)-1:
if sign == "+":
stack.append(operand)
elif sign == "-":
stack.append(-operand)
elif sign == "*" or sign == "/":
stack[-1] = stack[-1]*operand if sign == "*" else int(stack[-1]*1.0/operand)
operand = 0
sign = s[i]
return sum(stack)
class Solution(object):
def summaryRanges(self, nums):
"""
:type nums: List[int]
:rtype: List[str]
"""
n = len(nums)
ans = list()
j = 0
for i in range(n):
if i+1 < n and nums[i+1]==nums[i]+1:
continue
if i == j:
ans.append(str(nums[j]))
else:
ans.append(str(nums[j]) + "->" + str(nums[i]))
j = i+1
return ans
class Solution(object):
def majorityElement(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
ans = list()
n = len(nums)
if not nums:
print(ans)
cand1, cand2, count1, count2 = nums[0], nums[0], 0, 0
# 1.对抗阶段:获选人的票数互相低消
for num in nums:
if cand1==num: # 候选人cand1与num相等时,count1票数增加1
count1 += 1
elif cand2==num: # 候选人cand2与num相等时,count2票数增加1
count2 += 1
elif count1==0: # 候选人cand1的票数为0时,更换候选人cand1为num
cand1 = num
count1 += 1
elif count2==0: # 候选人cand2的票数为0时,更换候选人cand2为num
cand2 = num
count2 += 1
else: # 候选人cand1和cand2的与num不相等时,低消票数
count1 -= 1
count2 -= 1
# 2.计数阶段:计算剩下的候选人的票数是否符合要求
count1, count2 = 0, 0 # 初始化两个候选人的票数为0
for num in nums:
if cand1==num:
count1 += 1
elif cand2==num:
count2 += 1
if count1 > n//3:
ans.append(cand1)
if count2 > n//3:
ans.append(cand2)
return ans
class Solution(object):
def inorder(self, root):
return [] if not root else self.inorder(root.left) + [root.val] + self.inorder(root.right)
def kthSmallest(self, root, k):
"""
:type root: TreeNode
:type k: int
:rtype: int
"""
return self.inorder(root)[k-1]
思路
2的幂次方n二进制为1000…,其n-1的二进制为0111…,与操作后得到0,即为2的幂次方
class Solution(object):
def isPowerOfTwo(self, n):
"""
:type n: int
:rtype: bool
"""
if n==0:
return False
return True if n&n-1==0 else False
class MyQueue(object):
def __init__(self):
"""
Initialize your data structure here.
"""
self.a = list()
def push(self, x):
"""
Push element x to the back of queue.
:type x: int
:rtype: None
"""
self.a.append(x)
def pop(self):
"""
Removes the element from in front of queue and returns that element.
:rtype: int
"""
return self.a.pop(0)
def peek(self):
"""
Get the front element.
:rtype: int
"""
return self.a[0]
def empty(self):
"""
Returns whether the queue is empty.
:rtype: bool
"""
return not self.a
# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()
思路
分别计算n在个位(1个),十位(每十位的个位出现1次,如11,21,31…),百位(每百位的十位出现10次,如110,111,112…210,211,212…)…的1出现的个数后累加求和
由规律得到公式:
( n / 10 ∗ i ) ∗ i + m i n ( m a x ( n % 10 ∗ i − i + 1 , 0 ) , i ) (n/10*i)*i+min(max(n\%10*i-i+1, 0), i) (n/10∗i)∗i+min(max(n%10∗i−i+1,0),i)
class Solution(object):
def countDigitOne(self, n):
"""
:type n: int
:rtype: int
"""
i, ans = 1, 0
while i <= n:
ans =ans + (n//(10*i))*i+min(max(n%(10*i)-i+1, 0), i)
i *= 10
return ans
class Solution(object):
def isPalindrome(self, head):
"""
:type head: ListNode
:rtype: bool
"""
tmp = head
ans = list()
while tmp:
ans.append(tmp.val)
tmp = tmp.next
return ans==ans[::-1]
思路
class Solution(object):
# 快慢指针, slow指向链表中间
def halfList(self, head):
slow, fast = head, head
while fast.next and fast.next.next:
slow = slow.next
fast = fast.next.next
return slow
# 206. 反转链表(简单)
def reverseList(self, head):
p, c = None, head
while c:
n = c.next
c.next = p
p = c
c = n
return p
def isPalindrome(self, head):
"""
:type head: ListNode
:rtype: bool
"""
if not head or head.next==None:
return True
first = head # 链表前半部分
slow = self.halfList(head) # 找到中间结点
second_start = self.reverseList(slow.next) # 反转链表后半部分
second = second_start # 链表后半部分
while second!=None: # 判断是否回文,对比链表的前半部分和反转的后部分是否相同
if first.val != second.val:
return False
first = first.next
second = second.next
# 还原链表
first.next = self.reverseList(second_start)
return True
思路
遍历二叉搜索树,当遍历的结点x均大于p和q时,p和q均在x的左子树中;当x均小于p和q时,p和q均在x的右子树中;否则x未p和q的分叉点,即最近的公共祖先
class Solution(object):
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
x = root
while x:
if p.val < x.val and q.val < x.val:
x = x.left
elif p.val > x.val and q.val > x.val:
x = x.right
else:
return x
class Solution(object):
def __init__(self):
ans = None
def helper(self, root, p, q):
if not root:
return False
left = self.helper(root.left, p, q)
right = self.helper(root.right, p, q)
if (left and right) or ((root.val==p.val or root.val==q.val) and (right or left)):
self.ans = root
# p/q分别存在左右子树中 或 遍历的结点为p/q
return left or right or (root.val==p.val or root.val==q.val)
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
self.helper(root, p, q)
return self.ans
class Solution(object):
def deleteNode(self, node):
"""
:type node: ListNode
:rtype: void Do not return anything, modify node in-place instead.
"""
node.val = node.next.val
node.next = node.next.next
思路
遍历两遍:
第一遍: 计算从左0到i-1的乘积L存在输出数组output[i]中,即output[i]=L(nums[i-1]*output[i-1])
第二遍: 计算从右n-1到i+1的乘积R,更新output[i]=output[i]R,即output[i] = LR(L:i坐标左边数字的乘积,R:i右边数字的乘积)
class Solution(object):
def productExceptSelf(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
n = len(nums)
output = [1 for _ in range(n)]
for i in range(1, n):
output[i] = nums[i-1]*output[i-1]
R = 1
for i in range(n-1, -1, -1):
output[i] = output[i]*R
R *= nums[i]
return output
class Solution(object):
def maxSlidingWindow(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
n = len(nums)
if n*k==0:
return []
if k==1:
return nums
if n <=k:
return [max(nums)]
maxIdx, queue = 0, list() # 创建窗口最大值的索引和双向队列
for i in range(k):
while queue and nums[i] > nums[queue[-1]]: # 将比当前值小的索引移出队列
queue.pop()
queue.append(i) # 将当前值索引添加至双向队列中
if nums[i] > nums[maxIdx]: # 得到值最大的坐标maxIdx
maxIdx = i
ans = [nums[maxIdx]]
for i in range(k, n):
if queue and queue[0] == i-k: # 最大值坐标为i-k时不在窗口范围内(窗口范围为[i-k+1, i+1]),将其移除
queue.pop(0) # 移除队列头部
while queue and nums[i] > nums[queue[-1]]: # 将比当前值小的索引移出队列
queue.pop() # 移除队列尾部
queue.append(i) # 将当前值索引添加至双向队列中
ans.append(nums[queue[0]]) # 队列头部添加至输出队列中
return ans
class Solution(object):
def searchMatrix(self, matrix, target):
"""
:type matrix: List[List[int]]
:type target: int
:rtype: bool
"""
for i in range(len(matrix)):
if target in matrix[i]:
return True
return False
class Solution(object):
def diffWaysToCompute(self, input):
"""
:type input: str
:rtype: List[int]
"""
if input.isdigit(): # 纯数字时直接返回
return [int(input)]
ans = list()
for i, c in enumerate(input): # 遍历字符串
if c in ["+", "-", "*"]: # 字符是运算符时运算
left = self.diffWaysToCompute(input[:i]) # 求左边的操作数
right = self.diffWaysToCompute(input[i+1:]) # 求右边的操作数
for l in left:
for r in right:
if c == "+":
ans.append(l+r)
elif c == "-":
ans.append(l-r)
elif c == "*":
ans.append(l*r)
return ans
class Solution(object):
def isAnagram(self, s, t):
"""
:type s: str
:type t: str
:rtype: bool
"""
sList=[0 for _ in range(26)]
tList=[0 for _ in range(26)]
for c in s:
sList[ord(c)-97] += 1
for c in t:
tList[ord(c)-97] += 1
return sList==tList
思路
排序
class Solution(object):
def isAnagram(self, s, t):
"""
:type s: str
:type t: str
:rtype: bool
"""
return sorted(s)==sorted(t)
class Solution(object):
def __init__(self):
self.ans = list()
def dfs(self, root, path):
if not root:
return []
path.append(str(root.val))
if not root.left and not root.right: # 叶子节点
self.ans.append("->".join(path))
else:
self.dfs(root.left, path)
self.dfs(root.right, path)
path.pop()
def binaryTreePaths(self, root):
"""
:type root: TreeNode
:rtype: List[str]
"""
self.dfs(root, list())
return self.ans
class Solution(object):
def addDigits(self, num):
"""
:type num: int
:rtype: int
"""
ans = 0
while num>0:
ans += num%10
num //=10
if num == 0 and ans > 9: # ans大于9重新初始化num和ans
num = ans
ans = 0
return ans
class Solution(object):
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
visited1, visited2 = set(), set()
for num in nums:
if num not in visited1:
visited1.add(num)
else:
visited2.add(num)
return list(visited1-visited2)
# Write your MySQL query statement below
SELECT T.request_at AS `Day`,
ROUND(
SUM(
IF(T.STATUS='completed',0,1)
)
/
COUNT(T.STATUS),
2
) AS `Cancellation Rate`
FROM Trips AS T
JOIN Users AS U1 ON (T.client_id = U1.users_id AND U1.banned='No')
JOIN Users AS U2 ON (T.driver_id = U2.users_id AND U2.banned='No')
WHERE T.request_at BETWEEN '2013-10-01' AND '2013-10-03'
GROUP BY T.request_at
class Solution(object):
def isUgly(self, num):
"""
:type num: int
:rtype: bool
"""
if num == 0:
return False
while num%5==0:
num //= 5
while num%3==0:
num //=3
while num%2==0:
num >>=1 # 二进制左移1位,即为除以2
return num == 1
class Solution(object):
def nthUglyNumber(self, n):
"""
:type n: int
:rtype: int
"""
uglyNums = [1]
idx2, idx3, idx5 = 0, 0, 0
for _ in range(1, n):
uglyNum = min(uglyNums[idx2]*2, uglyNums[idx3]*3, uglyNums[idx5]*5)
uglyNums.append(uglyNum)
if uglyNum == uglyNums[idx2]*2:
idx2 += 1
if uglyNum == uglyNums[idx3]*3:
idx3 += 1
if uglyNum == uglyNums[idx5]*5:
idx5 += 1
return uglyNums[-1]
思路
参考 136. 只出现一次的数字
nums里的数和下标做异或操作:
初始化missingNum为len(nums)
没有出现的数字和下标异或:0^i = i
数字num和下标i相同时异或:num[i] ^ i = 0
class Solution(object):
def missingNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
n = len(nums)
missingNum = n
for i in range(n):
missingNum ^= nums[i] ^ i
return missingNum
思路
就酱
class Solution(object):
def missingNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
for num in range(len(nums)+1):
if num not in nums:
return num
class Solution(object):
def numberToWords(self, num):
"""
:type num: int
:rtype: str
"""
to19 = ['One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Eleven',
'Twelve', 'Thirteen', 'Fourteen', 'Fifteen', 'Sixteen', 'Seventeen', 'Eighteen', 'Nineteen']
tens = ['Twenty', 'Thirty', 'Forty', 'Fifty', 'Sixty', 'Seventy', 'Eighty', 'Ninety']
def helper(num):
if num < 20:
return to19[num-1:num] # 返回列表
if num < 100:
return [tens[num//10-2]] + helper(num%10)
if num < 1000:
return [to19[num//100-1]] + ['Hundred'] + helper(num%100)
for p, word in enumerate(['Thousand', 'Million', 'Billion']):
if num < 1000**(p+2):
return helper(num//1000**(p+1)) + [word] + helper(num%(1000**(p+1)))
return ' '.join(helper(num)) or 'Zero'
class Solution(object):
def hIndex(self, citations):
"""
:type citations: List[int]
:rtype: int
"""
citations.sort()
n = len(citations)
for i in range(n):
if citations[i]>=n-i:
return n-i
return 0
class Solution(object):
def hIndex(self, citations):
"""
:type citations: List[int]
:rtype: int
"""
n = len(citations)
for i in range(n):
if citations[i]>=n-i:
return n-i
return 0
class Solution(object):
def firstBadVersion(self, n):
"""
:type n: int
:rtype: int
"""
l, r = 1, n
while l<=r:
mid = (l+r)//2
if isBadVersion(mid):
r = mid-1
else:
l = mid+1
return l
import math
class Solution(object):
def numSquares(self, n):
"""
:type n: int
:rtype: int
"""
squareNums = [i**2 for i in range(1, int(math.sqrt(n)+1))]
dp = [float("inf") for _ in range(n+1)]
dp [0]= 0
for i in range(1, n+1):
for k in squareNums:
if i - k >= 0:
dp[i] = min(dp[i], dp[i-k]+1)
return dp[-1]
class Solution(object):
def addOperators(self, num, target):
"""
:type num: str
:type target: int
:rtype: List[str]
"""
def helper(index, pre, cur, numSum, s):
if index == n:
if numSum == target and cur == 0:
ans.append("".join(s[1:]))
return
cur = cur*10+int(num[index])
if cur > 0:
helper(index+1, pre, cur, numSum, s)
s.append('+') # 加
s.append(str(cur))
helper(index+1, cur, 0, numSum+cur, s)
s.pop()
s.pop()
if s:
s.append('-') # 减
s.append(str(cur))
helper(index+1, -cur, 0, numSum-cur, s)
s.pop()
s.pop()
s.append('*') # 乘
s.append(str(cur))
# 乘,用表达式的值减去pre再加上pre*cur, 如123,1+2*3-->(1+2)-2+(2*3),保证乘法的优先级
helper(index+1, pre*cur, 0, numSum-pre+(pre*cur), s)
s.pop()
s.pop()
n = len(num)
ans = list()
helper(0, 0, 0, 0, list())
return ans
思路
设置游标i为0,遍历数组nums,不为0的数字存储在数组前端,剩余的位置均为0
class Solution(object):
def moveZeroes(self, nums):
"""
:type nums: List[int]
:rtype: None Do not return anything, modify nums in-place instead.
"""
i = 0
for j in range(len(nums)):
if nums[j] != 0:
nums[i] = nums[j]
i += 1
for k in range(i, len(nums)):
nums[k] = 0
思路
设置游标i为0,遍历数组nums,当nums[j]不为0时和nums[i]交换,i往右移动
class Solution(object):
def moveZeroes(self, nums):
"""
:type nums: List[int]
:rtype: None Do not return anything, modify nums in-place instead.
"""
i = 0
for j in range(len(nums)):
if nums[j] != 0:
nums[i], nums[j] = nums[j], nums[i]
i += 1
思路
peek: 查看cache是否为空,不为空时直接返回,为空时执行next操作并记录值,返回该值
# Below is the interface for Iterator, which is already defined for you.
#
# class Iterator(object):
# def __init__(self, nums):
# """
# Initializes an iterator object to the beginning of a list.
# :type nums: List[int]
# """
#
# def hasNext(self):
# """
# Returns true if the iteration has more elements.
# :rtype: bool
# """
#
# def next(self):
# """
# Returns the next element in the iteration.
# :rtype: int
# """
class PeekingIterator(object):
def __init__(self, iterator):
"""
Initialize your data structure here.
:type iterator: Iterator
"""
self.iterator = iterator
self.cache = None
def peek(self):
"""
Returns the next element in the iteration without advancing the iterator.
:rtype: int
"""
if self.cache:
return self.cache
else:
self.cache = self.iterator.next()
return self.cache
def next(self):
"""
:rtype: int
"""
if not self.cache:
return self.iterator.next()
temp = self.cache
self.cache = None
return temp
def hasNext(self):
"""
:rtype: bool
"""
return self.cache != None or self.iterator.hasNext()
# Your PeekingIterator object will be instantiated and called as such:
# iter = PeekingIterator(Iterator(nums))
# while iter.hasNext():
# val = iter.peek() # Get the next element but not advance the iterator.
# iter.next() # Should return the same value as [val].
思路
class Solution(object):
def findDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
nums.sort()
for i in range(1, len(nums)):
if nums[i]==nums[i-1]:
return nums[i]
class Solution(object):
def gameOfLife(self, board):
"""
:type board: List[List[int]]
:rtype: None Do not return anything, modify board in-place instead.
"""
m, n = len(board), len(board[0])
change = list()
for i in range(m):
for j in range(n):
liveNum = 0
for tmp_i, tmp_j in [(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)]:
x, y = i+tmp_i, j+tmp_j
if 0<=x<m and 0<=y<n:
if board[x][y] == 1:
liveNum += 1
if board[i][j] == 1:
if liveNum < 2 or liveNum > 3:
change.append((i,j))
else:
if liveNum==3:
change.append((i, j))
for i, j in change:
board[i][j] = 0 if board[i][j]==1 else 1
return board
class Solution(object):
def wordPattern(self, pattern, s):
"""
:type pattern: str
:type s: str
:rtype: bool
"""
mapping = dict()
s = s.split()
if len(s) != len(pattern):
return False
for i in range(len(pattern)):
if pattern[i] not in mapping:
if s[i] not in mapping.values():
mapping[pattern[i]] = s[i]
else:
return False
else:
if mapping[pattern[i]] != s[i]:
return False
return True
class Solution(object):
def canWinNim(self, n):
"""
:type n: int
:rtype: bool
"""
return n%4!=0
class MedianFinder(object):
def __init__(self):
"""
initialize your data structure here.
"""
self.nums = list()
def addNum(self, num):
"""
:type num: int
:rtype: None
"""
self.nums.append(num)
def findMedian(self):
"""
:rtype: float
"""
self.nums.sort()
n = len(self.nums)
mid = n//2
if n%2!=0:
return self.nums[mid]
else:
return (self.nums[mid-1]+self.nums[mid])/2.0
# Your MedianFinder object will be instantiated and called as such:
# obj = MedianFinder()
# obj.addNum(num)
# param_2 = obj.findMedian()
class Codec:
def serialize(self, root):
"""Encodes a tree to a single string.
:type root: TreeNode
:rtype: str
"""
return "X," if not root else str(root.val)+',' + self.serialize(root.left) + self.serialize(root.right)
def deserialize(self, data):
"""Decodes your encoded data to tree.
:type data: str
:rtype: TreeNode
"""
data = data.split(',')
return self.buildTree(data)
def buildTree(self, data):
val = data.pop(0)
if val == "X":
return None
node = TreeNode(val)
node.left = self.buildTree(data)
node.right = self.buildTree(data)
return node
class Solution(object):
def getHint(self, secret, guess):
"""
:type secret: str
:type guess: str
:rtype: str
"""
A, B = 0, 0
secret, guess = list(secret), list(guess)
for i in range(len(secret)):
if secret[i] == guess[i]:
A+=1
secret[i] = 'A'
guess[i] = 'G'
for i in range(len(secret)):
if secret[i] != guess[i]:
if guess[i] in secret:
B += 1
secret[secret.index(guess[i])] = "B"
return str(A)+'A'+str(B)+'B'
思路
动态规划:
nums[i]大于nums[j]时dp[i]=max(dp[i], dp[j]+1)
class Solution(object):
def lengthOfLIS(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
n = len(nums)
dp = [1]*n
for i in range(1, n):
for j in range(i):
if nums[i]>nums[j]:
dp[i] = max(dp[i], dp[j]+1)
return max(dp)