1. 两数之和
为了对运行时间复杂度进行优化,我们需要一种更有效的方法来检查数组中是否存在目标元素。如果存在,我们需要找出它的索引。保持数组中的每个元素与其索引相互对应的最好方法是什么?哈希表。
通过以空间换取速度的方式,我们可以将查找时间从 O(n)降低到 O(1)。哈希表正是为此目的而构建的,它支持以 近似 恒定的时间进行快速查找。我用“近似”来描述,是因为一旦出现冲突,查找用时可能会退化到 O(n)。但只要你仔细地挑选哈希函数,在哈希表中进行查找的用时应当被摊销为 O(1)。
一个简单的实现使用了两次迭代。在第一次迭代中,我们将每个元素的值和它的索引添加到表中。然后,在第二次迭代中,我们将检查每个元素所对应的目标元素(target - nums[i])是否存在于表中。注意,该目标元素不能是 nums[i]本身!
事实证明,我们可以一次完成。在进行迭代并将元素插入到表中的同时,我们还会回过头来检查表中是否已经存在当前元素所对应的目标元素。如果它存在,那我们已经找到了对应解,并立即将其返回。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hashmap={}
for i,j in enumerate(nums):
tmp=target-nums[i]
if tmp in hashmap:
return hashmap[tmp], i
hashmap[j]=i
return none
69. x 的平方根
二分法
class Solution:
def mySqrt(self, x: int) -> int:
left=0
right=x//2+1
while left < right:
tmp=(left + right + 1)>> 1
if tmp**2>x:
right = tmp-1
else:
left=tmp
return left
75颜色分类
计数排序的两趟扫描算法。
class Solution:
def sortColors(self, nums: List[int]) -> None:
r, w = 0, 0
for num in nums:
if num == 0:
r += 1
elif num == 1:
w += 1
for i in range(len(nums)):
if i < r:
nums[i] = 0
elif i < r + w:
nums[i] = 1
else:
nums[i] = 2
三指针的方法
class Solution:
def sortColors(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
left, right = 0, len(nums)-1
cur = 0
while cur <= right:
if nums[cur] == 0:
nums[cur], nums[left] = nums[left], nums[cur]
left += 1
cur += 1
elif nums[cur] == 1:
cur += 1
else:
nums[cur], nums[right] = nums[right], nums[cur]
right -= 1
110. 平衡二叉树
递归的方法
class Solution:
def isBalanced(self, root: TreeNode) -> bool:
def height(node):
if not node:return 0
left = height(node.left)
right = height(node.right)
if left == -1 or right == -1 or abs(left-right) > 1:
return -1
return max(left,right) + 1
return height(root) != -1
144. 二叉树的前序遍历
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
if root is None:
return []
stack, output = [root, ], []
while stack:
root = stack.pop()
if root is not None:
output.append(root.val)
if root.right is not None:
stack.append(root.right)
if root.left is not None:
stack.append(root.left)
return output
167. 两数之和 II - 输入有序数组
我们可以使用 两数之和 的解法在 O(n^2) 时间 O(1) 空间暴力解决,也可以用哈希表在 O(n)时间和 O(n)空间内解决。然而,这两种方法都没有用到输入数组已经排序的性质,我们可以做得更好。
我们使用两个指针,初始分别位于第一个元素和最后一个元素位置,比较这两个元素之和与目标值的大小。如果和等于目标值,我们发现了这个唯一解。如果比目标值小,我们将较小元素指针增加一。如果比目标值大,我们将较大指针减小一。移动指针后重复上述比较知道找到答案。
使用双指针的方法
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
first=0
last=len(numbers)-1
while (first<last):
if numbers[first]+numbers[last]==target:
return first+1,last+1
elif numbers[first]+numbers[last]>target:
last-=1
else:
first+=1
return none
241. 为运算表达式设计优先级
函数diffWaysToCompute,先定义了列表end(存储结果),对函数接受的字符串进行遍历,在当前字符为运算符时以运算符为界将字符串分为L和R,再对L和R进行递归。如果当前字符串中没有运算符,也就是end为空时就算达到了“边界”,返回当前字符串的int类型
简单的说函数返回的就是当前字符串运算的所有可能性,diffWaysToCompute(“2”)返回的是end=[2],diffWaysToCompute(“45”)返回的为end = [20];diffWaysToCompute(“3-45”)返回的是end=[-18, -5]
class Solution:
def diffWaysToCompute(self, input: str) -> List[int]:
def helper(m, n, op):
if op == "+":
return m+n
elif op == "-":
return m-n
else:
return m*n
end = []
for i in range(len(input)):
if input[i] in "-+*":
for left in self.diffWaysToCompute(input[:i]):
for right in self.diffWaysToCompute(input[i+1:]):
output = helper(left, right, input[i])
end.append(output)
if len(end) == 0:
end.append(int(input))
return end
242. 有效的字母异位词
先比较长度应该就可以过一些数据了,然后因为是逐个字母检查的所以一旦发现不符合就可以退出来,效率得到了不少提升。
class Solution(object):
def isAnagram(self, s, t):
"""
:type s: str
:type t: str
:rtype: bool
"""
if len(s)!=len(t):
return false
c = set(t)
for i in c:
if t.count(i) != s.count(i):
return false
return True
409最长回文串
class Solution:
def longestPalindrome(self, s: str) -> int:
st=0
for c in set(s):
st+=s.count(c)//2 * 2
# st = sum([int(s.count(c) / 2) * 2 for c in set(s)])
if st%2 == 0 and st< len(s):
return st+1
else:
return st
455 分发饼干
尽量用小的饼干满足贪心指数小的小朋友。如果小的饼干满足不了贪心指数小的小朋友,就放弃这个小的饼干
class Solution:
def findContentChildren(self, g: List[int], s: List[int]) -> int:
g.sort()
s.sort()
gi=0
si=0
res=0
while gi < len(g) and si < len(s):
if g[gi] <= s[si]:
gi+=1
si+=1
res+=1
else:
si+=1
return res
(参考别人的)由于每一次都从数组 g 和数组 s 中取出最小者进行比较,因此比较容易想到使用小顶堆。
import heapq
class Solution:
def findContentChildren(self, g: List[int], s: List[int]) -> int:
heapq.heapify(g)
heapq.heapify(s)
res = 0
# 如果小的饼干满足不了贪心指数最小的小朋友,就放弃这个饼干
while g and s:
if s[0] >= g[0]:
heapq.heappop(g)
heapq.heappop(s)
res += 1
else:
heapq.heappop(s)
return res
513. 找树左下角的值‘’
class Solution:
def findBottomLeftValue(self, root: TreeNode) -> int:
queue = [root]
for node in queue:
queue += filter(None, (node.right, node.left))
return node.val