class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
i = j = 0
for i in range(len(nums)):
if nums != 0:
nums[j] , nums= nums , nums[j]
j += 1
这种写法为什么会work呢?因为这么做可以保证,在进行第 n 次替换的时候,之前的非零元素已经全部完成了替换,并且全部汇集到了前 n - 1 个位置,所以本次替换一定是没有问题的。
class Solution(object):
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.
"""
# two get pointers for nums1 and nums2
p1 = m - 1
p2 = n - 1
# set pointer for nums1
p = m + n - 1
# while there are still elements to compare
while p1 >= 0 and p2 >= 0:
if nums1[p1] < nums2[p2]:
nums1[p] = nums2[p2]
p2 -= 1
else:
nums1[p] = nums1[p1]
p1 -= 1
p -= 1
# add missing elements from nums2
nums1[:p2 + 1] = nums2[:p2 + 1]
FaceBook面试真题:Dot Product of Sparse Vectors
Suppose we have very large sparse vectors (most of the elements in vector are zeros)Find a data structure to store themCompute the Dot Product.
Follow-up:
What if one of the vectors is very small?
很容易想到,sparse vector可以用 dict (hashmap)来存。 对于稀疏矩阵,我们需要找到对应位置的数来乘,这个地方可以用到 two pointer 的来找。因为两个 sparse vector 的 (position, value) 可以是有序的。
a = [(1,2),(2,3),(100,5)]
b = [(0,5),(1,1),(100,6)]
i = 0; j = 0 # 两个 pointer
result = 0
while i < len(a) and j < len(b):
if a[0] == b[j][0]:
result += a[1] * b[j][1]
i += 1
j += 1
elif a[0] < b[j][0]:
i += 1
else:
j += 1
print(result)
二分法
二分查找也是一种非常有用的编程思想,他的实现方式也是通过不断变化左右指针得到的。
def binarySearch(nums, target):
left, right = 0, len(nums) - 1
while left <= right:
mid = (right + left)/2
if nums[mid] == target:
return mid
elif nums[mid] < target:
left = mid + 1
elif nums[mid] > target:
right = mid - 1
return -1
LeetCode 42. Trapping Rain Water
在解决这道题是,其实有两个难点。首先第一个难点就是,如何对这个问题建模。我们在建模的时候,不一定要顺着直观的感觉去走。比如本题中,如果直观的去建模的话,那就是要先找到有多少个“坑”,然后分别算每个“坑”能装多少水。但是当你去找“坑”的时候,你就会发现,“坑”的情况是很复杂的,而这种复杂恰恰就是程序难写的根源。
对于这一题,有一个非常简单的方法可以解决。我们现在不去找有多少坑,而是看每一个 bin 能对最终装水贡献多少。
class Solution:
def trap(self, height: List[int]) -> int:
if not height: return 0
n = len(height)
max_left = [0] * n
max_right = [0] * n
max_left[0] = height[0]
max_right[-1] = height[-1]
# 找位置i左边最大值
for i in range(1, n):
max_left = max(height, max_left[i-1])
# 找位置i右边最大值
for i in range(n-2, -1, -1):
max_right = max(height, max_right[i+1])
#print(max_left)
#print(max_right)
# 求结果
res = 0
for i in range(n):
res += min(max_left, max_right) - height
return res
2. 栈
class Solution:
def trap(self, height: List[int]) -> int:
if not height: return 0
n = len(height)
stack = []
res = 0
for i in range(n):
#print(stack)
while stack and height[stack[-1]] < height:
tmp = stack.pop()
if not stack: break
res += (min(height, height[stack[-1]]) - height[tmp]) * (i-stack[-1] - 1)
stack.append(i)
return res
3. 双指针
class Solution:
def trap(self, height: List[int]) -> int:
if not height: return 0
left = 0
right = len(height) - 1
res = 0
# 记录左右边最大值
left_max = height[left]
right_max = height[right]
while left < right:
if left_max < right_max:
res += left_max - height[left]
left += 1
left_max = max(left_max, height[left])
else:
res += right_max - height[right]
right -= 1
right_max = max(right_max, height[right])
return res
这道题还是比较难的,下面总结一下这道题目。