给出两个数组,写出一个方法求出它们的交集
结果中的每个元素必须是唯一的。
class Solution:
"""
@param nums1: an integer array
@param nums2: an integer array
@return: an integer array
"""
def intersection(self, nums1, nums2):
# write your code here
# 把两个数组变成集合
# 采用集合的交集运算
nums1_set = set(nums1)
nums2_set = set(nums2)
return list(nums1_set & nums2_set)
给定两个数组,计算两个数组的交集
每个元素出现次数得和在数组里一样
答案可以以任意顺序给出
-如果给定的数组已经排序了怎么办?如何优化算法?
-如果nums1的大小比num2的小怎么办?哪种算法更好?
-如果nums2的元素存储在磁盘上,并且内存受到限制,以至于不能一次将所有元素加载到内存中,该怎么办?
class Solution:
"""
@param nums1: an integer array
@param nums2: an integer array
@return: an integer array
"""
def intersection(self, nums1, nums2):
# write your code here
# 感觉题目挺简单的,但是自己没能实现
# 用字典维护数组1中每个元素出现的次数
# 然后遍历数组2,如果元素在dict中的次数>0,是交集
# 将出现次数减去1
counter = {}
for num in nums1:
if num not in counter:
counter[num] = 1
else:
counter[num] += 1
res = []
for num in nums2:
if num in counter and counter[num] > 0:
res.append(num)
counter[num] -= 1
return res
下方这个方法,nums2的元素存储在磁盘上,并且内存受到限制,以至于不能一次将所有元素加载到内存中,就没办法用高效地排序了。
如果是已经排序的数组,这样做倒是挺好的。
class Solution:
"""
@param nums1: an integer array
@param nums2: an integer array
@return: an integer array
"""
def intersection(self, nums1, nums2):
# write your code here
# 两数组排序,然后从头遍历
# 相等的话就加入结果中
nums1.sort()
nums2.sort()
m, n = len(nums1), len(nums2)
i, j = 0, 0
res = []
while i < m and j < n:
if i < m and j < n and nums1[i] == nums2[j]:
res.append(nums1[i])
i += 1
j += 1
if i < m and j < n and nums1[i] < nums2[j]:
i += 1
if i < m and j < n and nums1[i] > nums2[j]:
j += 1
return res
给出多个数组,求它们的交集。输出他们交集的大小。
输入的所有数组元素总数不超过500000。
题目数据每个数组里的元素没有重复。
class Solution:
"""
@param arrs: the arrays
@return: the number of the intersection of the arrays
"""
def intersectionOfArrays(self, arrs):
# write your code here
# 第一思路是转化为两数组求交集的问题
# 有点类似于合并K个数组的问题,转化为合并2个数组的问题
while len(arrs) > 1:
new_arrs = []
for i in range(0, len(arrs), 2):
if i + 1 < len(arrs):
new_arrs.append(self.intersection(arrs[i], arrs[i + 1]))
else:
new_arrs.append(arrs[i])
arrs = new_arrs[:]
return len(arrs[0])
def intersection(self, nums1, nums2):
return list(set(nums1) & set(nums2))
class Solution:
"""
@param arrs: the arrays
@return: the number of the intersection of the arrays
"""
def intersectionOfArrays(self, arrs):
# write your code here
# 因为每个数组里的元素没有重复,可以使用集合来做
# 多个数组的交集,两两来做
if len(arrs) == 0:
return 0
if len(arrs) == 1:
return len(arrs[0])
res = set(arrs[0])
for i in range(1, len(arrs)):
res = res & set(arrs[i])
return len(res)
将按升序排序的整数数组A和B合并,新数组也需有序。
class Solution:
"""
@param A: sorted integer array A
@param B: sorted integer array B
@return: A new sorted integer array
"""
def mergeSortedArray(self, A, B):
# write your code here
# 和合并两个排序链表的思路一样
# 从头遍历两个数组,把小的数放到新数组中
new_array = []
index_a, index_b = 0, 0
while index_a < len(A) and index_b < len(B):
if A[index_a] < B[index_b]:
new_array.append(A[index_a])
index_a += 1
else:
new_array.append(B[index_b])
index_b += 1
if index_a < len(A):
new_array.extend(A[index_a:])
if index_b < len(B):
new_array.extend(B[index_b:])
return new_array
class Solution:
"""
@param A: sorted integer array A
@param B: sorted integer array B
@return: A new sorted integer array
"""
def mergeSortedArray(self, A, B):
# write your code here
i, j = 0, 0
res = []
while i < len(A) and j < len(B):
if A[i] < B[j]:
res.append(A[i])
i += 1
else:
res.append(B[j])
j += 1
while i < len(A):
res.append(A[i])
i += 1
while j < len(B):
res.append(B[j])
j += 1
return res
合并两个排序的整数数组A和B变成一个新的数组。
你可以假设A具有足够的空间(A数组的大小大于或等于m+n)去添加B中的元素。数组A和B分别含有m和n个数。
class Solution:
"""
@param: A: sorted integer array A which has m elements, but size of A is m+n
@param: m: An integer
@param: B: sorted integer array B which has n elements
@param: n: An integer
@return: nothing
"""
def mergeSortedArray(self, A, m, B, n):
# write your code here
# 这个和第6题有什么区别吗?都是排序数组
# 但是这个题目要求return nothing,我理解合并后的数组放到A中
# 这次尝试不另开数组,直接存到A中
# 从后向前遍历,比较的时候,每次取较大的数放到A的后面
index_a = m - 1
index_b = n - 1
tail = m + n - 1
while index_a >= 0 and index_b >= 0:
if A[index_a] > B[index_b]:
A[tail] = A[index_a]
index_a -= 1
else:
A[tail] = B[index_b]
index_b -= 1
tail -= 1
while index_a >= 0:
A[tail] = A[index_a]
index_a -= 1
tail -= 1
while index_b >= 0:
A[tail] = B[index_b]
index_b -= 1
tail -= 1
class Solution:
"""
@param: A: sorted integer array A which has m elements, but size of A is m+n
@param: m: An integer
@param: B: sorted integer array B which has n elements
@param: n: An integer
@return: nothing
"""
def mergeSortedArray(self, A, m, B, n):
# write your code here
# 倒序遍历A和B并比较大小
# 大的数放到A的后面
i, j = m - 1, n - 1 # len(A) - 1, len(B) - 1是不对的
tail = m + n - 1
while i >= 0 and j >= 0:
if A[i] > B[j]:
A[tail] = A[i]
i -= 1
tail -= 1
else:
A[tail] = B[j]
j -= 1
tail -= 1
while i >= 0:
A[tail] = A[i]
i -= 1
tail -= 1
while j >= 0:
A[tail] = B[j]
j -= 1
tail -= 1
将 k 个有序数组合并为一个大的有序数组。
class Solution:
"""
@param arrays: k sorted integer arrays
@return: a sorted array
"""
def mergekSortedArrays(self, arrays):
# write your code here
# 类似合并K个排序链表的思路
# 转为合并2个排序数组问题
# 两两合并,直到只剩一个数组
# tmp = []
while len(arrays) > 1:
tmp = []
for index in range(0, len(arrays), 2):
if index + 1 < len(arrays):
tmp.append(self.merge2SortedArrays(arrays[index], arrays[index + 1]))
else:
tmp.append(arrays[index])
arrays = tmp[:]
return arrays[0]
def merge2SortedArrays(self, array1, array2):
new_array = []
index_1, index_2 = 0, 0
while index_1 < len(array1) and index_2 < len(array2):
if array1[index_1] < array2[index_2]:
new_array.append(array1[index_1])
index_1 += 1
else:
new_array.append(array2[index_2])
index_2 += 1
if index_1 < len(array1):
new_array.extend(array1[index_1:])
if index_2 < len(array2):
new_array.extend(array2[index_2:])
return new_array
将两个排序(升序)链表合并为一个新的升序排序链表
"""
Definition of ListNode
class ListNode(object):
def __init__(self, val, next=None):
self.val = val
self.next = next
"""
class Solution:
"""
@param l1: ListNode l1 is the head of the linked list
@param l2: ListNode l2 is the head of the linked list
@return: ListNode head of linked list
"""
def mergeTwoLists(self, l1, l2):
# write your code here
# 依次从头到尾比较两个链表的节点值
# 把小的节点值赋值到一个新的链表
dummy = ListNode(0)
tmp = dummy
while l1 and l2:
if l1.val < l2.val:
tmp.next = l1
l1 = l1.next
else:
tmp.next = l2
l2 = l2.next
tmp = tmp.next
if l1:
tmp.next = l1
if l2:
tmp.next = l2
return dummy.next
合并k个排序链表,并且返回合并后的排序链表。尝试分析和描述其复杂度。
先合并前两个,然后用得到的合并链表和第三个合并,依次向后。这样会time limit exceeded。
这不是一个好的方法
"""
Definition of ListNode
class ListNode(object):
def __init__(self, val, next=None):
self.val = val
self.next = next
"""
class Solution:
"""
@param lists: a list of ListNode
@return: The head of one sorted list.
"""
def mergeKLists(self, lists):
# write your code here
# 做过了合并两个排序链表的题目
# 拆解问题,将合并K个转为合并2个的问题
# 可以想到的一个容易实现的思路是:
# 将第一个和第二个合并,得到的新链表和第三个合并
# 依次向后,直到和最后一个链表合并
new_listnode = lists[0]
index = 1
while index < len(lists):
l2 = lists[index]
new_listnode = self.merge2Lists(new_listnode, l2)
index += 1
return new_listnode
def merge2Lists(self, new_listnode, l2):
dummy = ListNode(0)
tmp = dummy
while new_listnode and l2:
if new_listnode.val < l2.val:
tmp.next = new_listnode
new_listnode = new_listnode.next
else:
tmp.next = l2
l2 = l2.next
tmp = tmp.next
if new_listnode:
tmp.next = new_listnode
if l2:
tmp.next = l2
return dummy.next
优化了一下,先把列表中的链表两两合并,这样不停的两两合并,直到只剩一个链表。
"""
Definition of ListNode
class ListNode(object):
def __init__(self, val, next=None):
self.val = val
self.next = next
"""
class Solution:
"""
@param lists: a list of ListNode
@return: The head of one sorted list.
"""
def mergeKLists(self, lists):
# write your code here
# 还是转为合并2个排序链表
# 把链表两两合并,直到只剩下1个链表
while len(lists) > 1:
tmp = []
for index in range(0, len(lists), 2):
if index + 1 < len(lists):
tmp.append(self.merge2Lists(lists[index], lists[index + 1]))
else:
tmp.append(lists[index])
lists = tmp[:]
return lists[0]
def merge2Lists(self, l1, l2):
dummy = tail = ListNode(0)
while l1 and l2:
if l1.val < l2.val:
tail.next = l1
l1 = l1.next
else:
tail.next = l2
l2 = l2.next
tail = tail.next
if l1:
tail.next = l1
if l2:
tail.next = l2
return dummy.next
合并两个已排序的区间列表,并将其作为一个新的有序区间列表返回。新的区间列表应该通过拼接两个列表的区间并按升序排序。
同一个列表中的区间一定不会重叠。
不同列表中的区间可能会重叠。
"""
Definition of Interval.
class Interval(object):
def __init__(self, start, end):
self.start = start
self.end = end
"""
class Solution:
"""
@param list1: one of the given list
@param list2: another list
@return: the new sorted list of interval
"""
def mergeTwoInterval(self, list1, list2):
# write your code here
# 有点类似于合并两个数组
# 记录最后一个放进去的interval,和下一个interval做比较
i, j = 0, 0
intervals = []
while i < len(list1) and j < len(list2):
if list1[i].start < list2[j].start:
self.pushBack(intervals, list1[i])
i += 1
else:
self.pushBack(intervals, list2[j])
j += 1
while i < len(list1):
self.pushBack(intervals, list1[i])
i += 1
while j < len(list2):
self.pushBack(intervals, list2[j])
j += 1
return intervals
def pushBack(self, intervals, interval):
if intervals == []:
intervals.append(interval)
return
last_interval = intervals[-1]
if last_interval.end < interval.start:
intervals.append(interval)
else:
last_interval.end = max(last_interval.end, interval.end)
将K个排序的间隔列表合并到一个排序的间隔列表中,你需要合并重叠的间隔。
"""
Definition of Interval.
class Interval(object):
def __init__(self, start, end):
self.start = start
self.end = end
"""
class Solution:
"""
@param intervals: the given k sorted interval lists
@return: the new sorted interval list
"""
def mergeKSortedIntervalLists(self, intervals):
# write your code here
# 做过了合并两个排序间隔列表
# 将合并k的问题,转化为合并两个的问题
# 两两合并,直到只剩一个
while len(intervals) > 1:
tmp = []
for i in range(0, len(intervals), 2):
if i + 1 < len(intervals):
tmp.append(self.merge2SortedIntervalLists(intervals[i], intervals[i + 1]))
else:
tmp.append(intervals[i])
intervals = tmp[:]
return intervals[0]
def merge2SortedIntervalLists(self, interval1, interval2):
i, j = 0, 0
res = []
while i < len(interval1) and j < len(interval2):
if interval1[i].start < interval2[j].start:
self.pushBack(res, interval1[i])
i += 1
else:
self.pushBack(res, interval2[j])
j += 1
while i < len(interval1):
self.pushBack(res, interval1[i])
i += 1
while j < len(interval2):
self.pushBack(res, interval2[j])
j += 1
return res
def pushBack(self, res, interval):
if res == []:
res.append(interval)
return
last_interval = res[-1]
if last_interval.end < interval.start:
res.append(interval)
else:
last_interval.end = max(last_interval.end, interval.end)
用一个数组实现三个栈。你可以假设这三个栈都一样大并且足够大。你不需要担心如果一个栈满了之后怎么办。
class ThreeStacks:
"""
@param: size: An integer
"""
def __init__(self, size):
# do intialization if necessary
self.size = size
self.nums = [[], [], []]
"""
@param: stackNum: An integer
@param: value: An integer
@return: nothing
"""
def push(self, stackNum, value):
# Push value into stackNum stack
self.nums[stackNum].append(value)
"""
@param: stackNum: An integer
@return: the top element
"""
def pop(self, stackNum):
# Pop and return the top element from stackNum stack
return self.nums[stackNum].pop()
"""
@param: stackNum: An integer
@return: the top element
"""
def peek(self, stackNum):
# Return the top element
return self.nums[stackNum][-1]
"""
@param: stackNum: An integer
@return: true if the stack is empty else false
"""
def isEmpty(self, stackNum):
# write your code here
return len(self.nums[stackNum]) == 0
通过两个队列实现一个栈。队列是先进先出(FIFO)。这意味着不能直接弹出队列中的最后一个元素。
输入:
push(1)
pop()
push(2)
isEmpty() // return false
top() // return 2
pop()
isEmpty() // return true
基本概念:队列是先进先出。有放入、取出元素等操作。
栈是后进先出,栈有压入、弹出,访问栈顶元素,栈大小,栈是否为空等操作。
这个题目的思路是一个队列用来保存栈的元素,另一个队列用来配合实现栈的压入、弹出、访问栈顶元素。
2021年6月二刷时对这样方法的理解:入栈操作时,先放到辅助队列,然后把主队列的元素移出放到辅助队列。这样辅助队列的队头元素就是栈顶元素了(最后入的),这是在把辅助队列和主队列交换。
from collections import deque
class Stack:
"""
queue1用来保存栈的元素
queue2用来配合实现压入、弹出等操作
"""
def __init__(self):
self.queue1 = deque()
self.queue2 = deque()
"""
@param: x: An integer
@return: nothing
"""
def push(self, x):
# write your code here
self.queue2.append(x)
while self.queue1:
self.queue2.appendleft(self.queue1.pop())
self.queue1, self.queue2 = self.queue2, self.queue1
"""
@return: nothing
"""
def pop(self):
# write your code here
return self.queue1.pop()
"""
@return: An integer
"""
def top(self):
# write your code here
return self.queue1[-1]
"""
@return: True if the stack is empty
"""
def isEmpty(self):
# write your code here
return not self.queue1
思路时:入栈时看主队列是否为空,不为空的话,移出放到辅助队列。然后入栈放到主队列,再把辅助队列的元素移出放到主队列。这样就实现了主队列的队头元素为栈顶元素。
class Stack:
# 两个队列,queue1为主队列,存储栈内元素
# queue2为辅助队列,实现入栈和出栈操作
# 入栈时,先把主队列元素一一移出放到辅助队列
# 然后把元素放到主队列,再把辅助队列的元素移出放入主队列
def __init__(self):
self.queue1 = []
self.queue2 = []
"""
@param: x: An integer
@return: nothing
"""
def push(self, x):
# write your code here
while self.queue1 != []:
self.queue2.append(self.queue1.pop())
self.queue1.append(x)
while self.queue2 != []:
self.queue1.append(self.queue2.pop())
"""
@return: nothing
"""
def pop(self):
# write your code here
self.queue1.pop(0)
"""
@return: An integer
"""
def top(self):
# write your code here
return self.queue1[0]
"""
@return: True if the stack is empty
"""
def isEmpty(self):
# write your code here
return not self.queue1
给一个整数数组 nums,求出下标从 i 到 j 的元素和(i ≤ j),i 跟 j对应的元素也包括在内。
你可以认为给出的数组不会发生变化。
会调用非常多次 sumRange 函数。
很常用的前缀和思路
class NumArray(object):
def __init__(self, nums):
"""
:type nums: List[int]
"""
# self.nums = nums
self.prefix_sum = [0] * (len(nums) + 1)
for i in range(len(nums)):
self.prefix_sum[i + 1] = self.prefix_sum[i] + nums[i]
def sumRange(self, i, j):
"""
:type i: int
:type j: int
:rtype: int
"""
return self.prefix_sum[j + 1] - self.prefix_sum[i]
# Your NumArray object will be instantiated and called as such:
# obj = NumArray(nums)
# param_1 = obj.sumRange(i,j)
给一 二维矩阵,计算由左上角 (row1, col1) 和右下角 (row2, col2) 划定的矩形内元素和.
你可以假设矩阵不变
对函数 sumRegion 的调用次数有很多次
你可以假设 row1 ≤ row2 并且 col1 ≤ col2
class NumMatrix:
"""
@param: matrix: a 2D matrix
"""
def __init__(self, matrix):
# do intialization if necessary
# 运用前缀和的思想,计算(0, 0)到每个点的矩阵和
# dp[i][j]表示左上角到(i, j)点的矩阵和
# dp[i][j] = dp[i][j-1] + dp[i-1][j] - dp[i-1][j-1] + matrix[i][j]
# 另外,为了避免多次重复计算,
# 在初始化时就计算好前缀和
if len(matrix) == 0 or len(matrix[0]) == 0:
return
n, m = len(matrix), len(matrix[0])
self.dp = [[0 for col in range(m + 1)] for row in range(n + 1)]
for row in range(n):
for col in range(m):
self.dp[row + 1][col + 1] = self.dp[row][col + 1] + self.dp[row + 1][col] \
- self.dp[row][col] + matrix[row][col]
"""
@param: row1: An integer
@param: col1: An integer
@param: row2: An integer
@param: col2: An integer
@return: An integer
"""
def sumRegion(self, row1, col1, row2, col2):
# write your code here
return self.dp[row2 + 1][col2 + 1] - self.dp[row2 + 1][col1] - self.dp[row1][col2 + 1] \
+ self.dp[row1][col1]
# Your NumMatrix object will be instantiated and called as such:
# obj = NumMatrix(matrix)
# param_1 = obj.sumRegion(row1,col1,row2,col2)
给定一个整数矩阵,请找出一个子矩阵,使得其数字之和等于0.输出答案时,请返回左上数字和右下数字的坐标。
如果有多个答案, 你可以返回其中任意一个.
class Solution:
"""
@param: matrix: an integer matrix
@return: the coordinate of the left-up and right-down number
"""
def submatrixSum(self, matrix):
# write your code here
# 第一思路是暴力,枚举所有的子矩阵,求矩阵和
n, m = len(matrix), len(matrix[0])
for row1 in range(n):
for row2 in range(row1, n):
for col1 in range(m):
for col2 in range(col1, m):
sum_region = sum(matrix[row1][col1:col2 + 1]) + sum(matrix[row2][col1:col2 + 1])
if sum_region == 0:
return [[row1, col1], [row2, col2]]
return [[-1, 1], [-1, -1]]
# return None
给出一个大小为 n x n 的矩阵,里面元素为 正整数 和 负整数 ,找到具有最大和的子矩阵。
class Solution:
"""
@param matrix: the given matrix
@return: the largest possible sum
"""
def maxSubmatrix(self, matrix):
# write your code here
# 把二维矩阵向下压缩,就变成了一维数组
# 本题采用这个思想,就变成了求数组的最大子数组
if len(matrix) == 0 or len(matrix[0]) == 0:
return 0
import sys
res = -sys.maxsize
m, n = len(matrix), len(matrix[0])
for i in range(m):
array = [0] * n
for j in range(i, m):
for k in range(n):
array[k] += matrix[j][k]
max_subArraySum = self.maxSubArray(array)
res = max(res, max_subArraySum)
return res
def maxSubArray(self, array):
import sys
max_sum, min_sum = -sys.maxsize, 0
prefix_sum = 0
for num in array:
prefix_sum += num
max_sum = max(max_sum, prefix_sum - min_sum)
min_sum = min(min_sum, prefix_sum)
return max_sum
给出一个字符串,找出第一个只出现一次的字符。假设只出现一次的字符数量大于等于1。
class Solution:
"""
@param str: str: the given string
@return: char: the first unique character in a given string
"""
def firstUniqChar(self, str):
# Write your code here
# 使用hash表存下每个char出现的次数
# 遍历str,如果char出现次数为1则返回
counter = {}
for char in str:
counter[char] = counter.get(char, 0) + 1
for char in str:
if counter[char] == 1:
return char
设计一个数据结构实现在平均 O(1) 的复杂度下执行以下所有的操作。
insert(val): 如果这个元素不在set中,则插入。
remove(val): 如果这个元素在set中,则从set中移除。
getRandom: 随机从set中返回一个元素。每一个元素返回的可能性必须相同。
class RandomizedSet:
def __init__(self):
# do intialization if necessary
# 数组用来保存元素
# 字典用来保存元素和其在数组中的索引
self.nums = []
self.val2index = {}
"""
@param: val: a value to the set
@return: true if the set did not already contain the specified element or false
"""
def insert(self, val):
# write your code here
if val in self.val2index:
return False
self.nums.append(val)
self.val2index[val] = len(self.nums) - 1
return True
"""
@param: val: a value from the set
@return: true if the set contained the specified element or false
"""
def remove(self, val):
# write your code here
if val not in self.val2index:
return False
index = self.val2index[val]
self.val2index[self.nums[-1]] = index
self.nums[index], self.nums[-1] = self.nums[-1], self.nums[index]
self.nums.pop()
del self.val2index[val]
return True
"""
@return: Get a random element from the set
"""
def getRandom(self):
# write your code here
import random
return self.nums[random.randint(0, len(self.nums) - 1)]
# Your RandomizedSet object will be instantiated and called as such:
# obj = RandomizedSet()
# param = obj.insert(val)
# param = obj.remove(val)
# param = obj.getRandom()
给出一串整数流和窗口大小,计算滑动窗口中所有整数的平均值。
注意不必要把所有的数据流都存在数组中,一边存新的一边删除老的
class MovingAverage(object):
"""
@param: size: An integer
"""
def __init__(self, size):
# do intialization if necessary
self.size = size
self.nums = []
self.sum = 0
"""
@param: val: An integer
@return:
"""
def next(self, val):
# write your code here
if len(self.nums) == self.size:
self.sum -= self.nums[0]
del self.nums[0]
self.sum += val
self.nums.append(val)
return self.sum / len(self.nums)
# Your MovingAverage object will be instantiated and called as such:
# obj = MovingAverage(size)
# param = obj.next(val)
在一个数组中找到前K大的数
class Solution:
"""
@param nums: an integer array
@param k: An integer
@return: the top k largest numbers in array
"""
def topk(self, nums, k):
# write your code here
# 时间复杂度O(nlogn)
nums.sort()
return nums[-1:-k - 1:-1]
正如标题所述,你只能使用两个栈来实现队列的一些操作。
队列应支持push(element),pop() 和 top(),其中pop是弹出队列中的第一个(最前面的)元素。
pop和top方法都应该返回第一个元素的值。
假设调用pop()函数的时候,队列非空
挑战
仅使用两个栈来实现它,不使用任何其他数据结构,push,pop 和 top的复杂度都应该是均摊O(1)的
看答案使用两个列表来实现的,并没有使用栈。先自己实现了看看。
栈1来保存元素,栈2来辅助实现队列的操作
其实列表的结构和栈是挺像的,append类似push,pop也是类似的。也是先进的后出,后进的先出。
先把元素放到栈2,然后再倒出来放到栈1
class MyQueue:
def __init__(self):
# do intialization if necessary
self.stack1 = []
self.stack2 = []
"""
@param: element: An integer
@return: nothing
"""
def push(self, element):
# write your code here
self.stack2.append(element)
"""
@return: An integer
"""
def pop(self):
# write your code here
if self.stack1:
return self.stack1.pop()
while self.stack2:
self.stack1.append(self.stack2.pop())
return self.stack1.pop()
"""
@return: An integer
"""
def top(self):
# write your code here
if self.stack1:
return self.stack1[-1]
while self.stack2:
self.stack1.append(self.stack2.pop())
return self.stack1[-1]
从一个栈依次pop放入另一栈以后,原来在栈顶的元素就跑到栈底了,而原来在栈底的元素就到了栈顶。
队列却没有这样的特点,从一个队列依次弹出放入另一个队列,元素的顺序不变。
class MyQueue:
# 两个栈,一个为主栈,存储元素
# 一个为辅助栈,
# 入队列时,先入辅助栈,然后把主栈元素也放入辅助栈
# 这样在辅助栈就实现了后入的元素在栈底
# 交换辅助栈和主站
# 上面写的思路是错误的。。。
# 先入辅助栈,pop的时候看主栈是否为空,为空的话,
# 把辅助栈的移出放到主栈,然后pop
# 不为空的话,就直接pop
def __init__(self):
# do intialization if necessary
self.stack1 = []
self.stack2 = []
"""
@param: element: An integer
@return: nothing
"""
def push(self, element):
# write your code here
self.stack2.append(element)
"""
@return: An integer
"""
def pop(self):
# write your code here
if self.stack1:
return self.stack1.pop()
else:
while self.stack2:
self.stack1.append(self.stack2.pop())
return self.stack1.pop()
"""
@return: An integer
"""
def top(self):
# write your code here
if self.stack1:
return self.stack1[-1]
else:
while self.stack2:
self.stack1.append(self.stack2.pop())
return self.stack1[-1]
实现一个栈,可以使用除了栈之外的数据结构
class Stack:
def __init__(self):
# 使用列表来实现栈操作试试
self.nums = []
"""
@param: x: An integer
@return: nothing
"""
def push(self, x):
# write your code here
self.nums.append(x)
"""
@return: nothing
"""
def pop(self):
# write your code here
return self.nums.pop()
"""
@return: An integer
"""
def top(self):
# write your code here
return self.nums[-1]
"""
@return: True if the stack is empty
"""
def isEmpty(self):
# write your code here
return not self.nums
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/min-stack
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class MinStack:
def __init__(self):
"""
initialize your data structure here.
"""
# 构造一个辅助栈,放每个栈顶元素对应的最小值
# 每push一个元素,和辅助栈栈顶元素比较大小
self.stack = []
self.min_stack = [math.inf]
def push(self, val: int) -> None:
self.stack.append(val)
if val < self.min_stack[-1]:
self.min_stack.append(val)
else:
self.min_stack.append(self.min_stack[-1])
def pop(self) -> None:
self.stack.pop()
self.min_stack.pop()
def top(self) -> int:
return self.stack[-1]
def getMin(self) -> int:
return self.min_stack[-1]
# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(val)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()
class MinStack:
# 用列表来实现栈,在用一个辅助列表来存储主栈栈顶元素对应的最小值
def __init__(self):
"""
initialize your data structure here.
"""
self.stack1 = []
self.stack2 = []
def push(self, val: int) -> None:
self.stack1.append(val)
if self.stack2 == []:
self.stack2.append(val)
else:
if val < self.stack2[-1]:
self.stack2.append(val)
else:
self.stack2.append(self.stack2[-1])
def pop(self) -> None:
self.stack1.pop()
self.stack2.pop()
def top(self) -> int:
return self.stack1[-1]
def getMin(self) -> int:
return self.stack2[-1]
给一个连续的数据流,写一个函数返回终止数字到达时的第一个唯一数字(包括终止数字),如果找不到这个终止数字, 返回 -1.
class Solution:
"""
@param nums: a continuous stream of numbers
@param number: a number
@return: returns the first unique number
"""
def firstUniqueNumber(self, nums, number):
# Write your code here
# 遍历数据流,记录下每个数字出现的次数
# 再次遍历,返回第一个唯一的数字
counter = {}
for digit in nums:
counter[digit] = counter.get(digit, 0) + 1
if digit == number:
break
else:
return -1
for digit in counter:
if counter[digit] == 1:
return digit
return -1
每个学生有两个属性 ID 和 scores。找到每个学生最高的5个分数的平均值。
'''
Definition for a Record
class Record:
def __init__(self, id, score):
self.id = id
self.score = score
'''
class Solution:
# @param {Record[]} results a list of
# @return {dict(id, average)} find the average of 5 highest scores for each person
# (student_id, average_score)
def highFive(self, results):
# Write your code here
# 遍历找到每个学习最高的5个分数
hash = {}
for student in results:
if student.id not in hash:
hash[student.id] = []
hash[student.id].append(student.score)
if len(hash[student.id]) > 5:
index = 0
for i in range(1, 6):
if hash[student.id][i] < hash[student.id][index]:
index = i
hash[student.id].pop(index)
for student in hash:
hash[student] = sum(hash[student]) / 5.0
return hash
如果一个数只有质数因子2,3,5 ,那么这个数是一个丑数。
前10个丑数分别为 1, 2, 3, 4, 5, 6, 8, 9, 10, 12…设计一个算法,找出第N个丑数。
我们可以认为 1 也是一个丑数。
class Solution:
"""
@param n: An integer
@return: return a integer as description.
"""
def nthUglyNumber(self, n):
# write your code here
# 用堆来做,自己尝试实现一下
# 每次弹出一个,弹到第n次的时候就是
# 第n个丑数
import heapq
heap = [1]
visited = set([1])
for i in range(n):
val = heapq.heappop(heap)
for factor in [2, 3, 5]:
if val * factor in visited:
continue
visited.add(val * factor)
heapq.heappush(heap, val * factor)
return val
找到一个无序数组中第K小的数
挑战:O(nlogn)的算法固然可行, 但如果你能 O(n) 解决, 那就非常棒了.
第k小元素,第k大元素,三种方法
内置排序算法、利用堆、快速选择
需要好好理解和掌握快速选择的程序,记住模板。
class Solution:
"""
@param k: An integer
@param nums: An integer array
@return: kth smallest element
"""
def kthSmallest(self, k, nums):
# write your code here
# 直接使用内置的排序算法就行,但是时间复杂度是O(nlogn)
# 感觉nlogn已经挺快了,不知道为啥非要努力实现O(n)
# version 1 O(nlogn)
# nums.sort()
# return nums[k - 1]
# version 2
# 快速选择算法,其实用的也是划分的思想
# 或者说划分借鉴了快速选择算法
return self.quickSelect(nums, 0, len(nums) - 1, k - 1)
def quickSelect(self, nums, start, end, k):
if start == end:
return nums[start]
left = start
right= end
pivot = nums[(left + right) // 2]
while left <= right:
while left <= right and nums[left] < pivot:
left += 1
while left <= right and nums[right] > pivot:
right -= 1
if left <= right:
nums[left], nums[right] = nums[right], nums[left]
left += 1
right -= 1
if k <= right and right >= start:
self.quickSelect(nums, start, right, k)
if k >= left and left <= end:
self.quickSelect(nums, left, end, k)
return nums[k]
找到数组中第K大的元素,N远大于K。请注意你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素
你可以改变数组中元素的位置
相关的题目还有第五题,要掌握快速选择算法,掌握堆的使用
class Solution:
"""
@param nums: an integer unsorted array
@param k: an integer from 1 to n
@return: the kth largest element
"""
def kthLargestElement2(self, nums, k):
# write your code here
# 直接把数组sort,然后返回nums[-k]?
# 时间复杂度时O(nlogn)
# nums.sort()
# return nums[-k]
# 题目应该不是让这么做的,那是让怎么做的呢?
# 用堆来做试试,遍历数组,让堆里保持只有k个
# 时间复杂度是O(n)
import heapq
heap = []
for num in nums:
heapq.heappush(heap, num)
if len(heap) > k:
heapq.heappop(heap)
return heapq.heappop(heap)
实现一个数据结构,提供下面两个接口
1.add(number) 添加一个元素
2.topk() 返回此数据结构中最大的k个数字。当我们创建数据结构时,k是给定的。
先用数组试试,没add一个数就把数组排序一次
class Solution:
"""
@param: k: An integer
"""
def __init__(self, k):
# do intialization if necessary
self.k = k
self.nums = []
"""
@param: num: Number to be added
@return: nothing
"""
def add(self, num):
# write your code here
self.nums.append(num)
self.nums.sort()
"""
@return: Top k element
"""
def topk(self):
# write your code here
if self.k > len(self.nums):
return self.nums[-1::-1]
else:
return self.nums[-1:-self.k - 1:-1]
用堆来实现试试,如果堆里的数超过k了,就弹出最小的。
import heapq
class Solution:
"""
@param: k: An integer
"""
def __init__(self, k):
# do intialization if necessary
self.k = k
self.heap = []
"""
@param: num: Number to be added
@return: nothing
"""
def add(self, num):
# write your code here
heapq.heappush(self.heap, num)
if len(self.heap) > self.k:
heapq.heappop(self.heap)
"""
@return: Top k element
"""
def topk(self):
# write your code here
return sorted(self.heap, reverse=True)
在二维空间里给定一些 points 和一个 origin,从 points 中找到 k 个离 origin 欧几里得距离最近的点。按照欧几里得距离由小到大返回。如果两个点有相同欧几里得距离,则按照x值来排序;若x值也相同,就再按照y值排序。
"""
Definition for a point.
class Point:
def __init__(self, a=0, b=0):
self.x = a
self.y = b
"""
class Solution:
"""
@param points: a list of points
@param origin: a point
@param k: An integer
@return: the k closest points
"""
def kClosest(self, points, origin, k):
# write your code here
# 要k个距离最近的点,可以考虑使用堆
# 堆顶是最小的元素,超过k以后,就弹出堆顶元素
# 所以存入堆的应该是距离的负数,坐标的负数
import heapq
heap = []
for point in points:
distance = self.getDistance(point, origin)
heapq.heappush(heap, (-distance, -point.x, -point.y))
if len(heap) > k:
heapq.heappop(heap)
res = []
while heap:
_, x, y = heapq.heappop(heap)
res.append(Point(-x, -y))
res.reverse()
return res
def getDistance(self, point1, point2):
return (point1.x - point2.x) ** 2 + (point1.y - point2.y) ** 2
给定一个由n个整数组成的数组,找到给定长度k的连续子数组,该子数组具有最大平均值。你需要输出最大平均值。
1 <= k <= n <= 30,000.
给定数组的元素范围是[-10,000, 10,000]。
class Solution:
"""
@param nums: an array
@param k: an integer
@return: the maximum average value
"""
def findMaxAverage(self, nums, k):
# Write your code here
# 因为是给定长度的子数组
# 题目可以转化为求给定长度的和最大的子数组
# 运用前缀和的思想,遍历数组
prefix_sum = [0] * (len(nums) + 1)
for i in range(len(nums)):
prefix_sum[i + 1] = prefix_sum[i] + nums[i]
import sys
max_sum = -sys.maxsize
for i in range(len(nums)):
if i + k > len(nums):
break
max_sum = max(max_sum, prefix_sum[i + k] - prefix_sum[i])
return max_sum * 1.0 / k
给出一个整数数组,有正有负。找到这样一个子数组,他的长度大于等于 k,且平均值最大。
保证数组的大小 >= k
class Solution:
"""
@param nums: an array with positive and negative numbers
@param k: an integer
@return: the maximum average
"""
def maxAverage(self, nums, k):
# write your code here
# 遍历长度大于等于k的子数组,求平均值,顺便打擂台
prefix_sum = [0] * (len(nums) + 1)
for i in range(len(nums)):
prefix_sum[i + 1] = prefix_sum[i] + nums[i]
import sys
max_average = -sys.maxsize
for i in range(len(nums)):
if i + k - 1 > len(nums) - 1:
break
for j in range(i + k - 1, len(nums)):
average = (prefix_sum[j + 1] - prefix_sum[i]) / (j - i + 1)
max_average = max(max_average, average)
return max_average
给定一个整数数组,找到和为 0 的子数组。你的代码应该返回满足要求的子数组的起始位置和结束位置
至少有一个子数组的和为 0
class Solution:
"""
@param nums: A list of integers
@return: A list of integers includes the index of the first number and the index of the last number
"""
def subarraySum(self, nums):
# write your code here
# 前缀和的思路
# 如果[start, end]区间的和为0
# 那么start之前的数之和、end之前包括end的数之和
# 是相等的
# 遍历前缀和,直到遇到相等的前缀和
prefix_hash = {0: -1}
prefix_sum = 0
for i in range(len(nums)):
prefix_sum += nums[i]
if prefix_sum in prefix_hash:
return [prefix_hash[prefix_sum] + 1, i]
prefix_hash[prefix_sum] = i
return [-1, -1]
给定一个整数数组,找到一个和最接近于零的子数组。返回满足要求的子数组的起始位置和结束位置。
class Solution:
"""
@param: nums: A list of integers
@return: A list of integers includes the index of the first number and the index of the last number
"""
def subarraySumClosest(self, nums):
# write your code here
# 开始也没有思路,看了答案
# 运用前缀和思想
# 将前缀和排序,相邻两个是最接近的
# 找到最接近的,记录索引
prefix_sum = [(0, -1)]
for i in range(len(nums)):
prefix_sum.append((prefix_sum[-1][0] + nums[i], i))
prefix_sum.sort()
import sys
closest = sys.maxsize
res = []
for i in range(1, len(prefix_sum)):
if closest > prefix_sum[i][0] - prefix_sum[i - 1][0]:
closest = prefix_sum[i][0] - prefix_sum[i - 1][0]
left = min(prefix_sum[i][1], prefix_sum[i - 1][1]) + 1
right = max(prefix_sum[i][1], prefix_sum[i - 1][1])
res = [left, right]
return res
给定一个正整数数组 A 和一个区间. 返回和在给定区间范围内的子数组数量.
子数组是原数组下标连续的一段元素,至少包含一个元素.
class Solution:
"""
@param A: An integer array
@param start: An integer
@param end: An integer
@return: the number of possible answer
"""
def subarraySumII(self, A, start, end):
# write your code here
# 运用前缀和的思想
# 然后遍历前缀和,统计在给定区间的子数组数量
# prefix_sum = [0]
# counter = 0
# for num in A:
# prefix_sum.append(prefix_sum[-1] + num)
# for i in range(len(prefix_sum)):
# for j in range(i + 1, len(prefix_sum)):
# if start <= prefix_sum[j] - prefix_sum[i] <= end:
# counter += 1
# return counter
# 上面的解法会超时,
给定一个整数数组,找到一个具有最大和的子数组,返回其最大和。
每个子数组的数字在数组中的位置应该是连续的。
import sys
class Solution:
"""
@param nums: A list of integers
@return: A integer indicate the sum of max subarray
"""
def maxSubArray(self, nums):
# write your code here
# 先参考答案中的前缀和思路来做
# prefix_sum表示前i个数的和
# max_sum表示最大的子数组和
# min_sum表示前i个数中最小的前缀和
# 遍历每一个前缀和,
# 打擂台得到max_sum和min_sum
max_sum, min_sum = -sys.maxsize, 0
prefix_sum = 0
for num in nums:
prefix_sum += num
max_sum = max(max_sum, prefix_sum - min_sum)
min_sum = min(min_sum, prefix_sum)
return max_sum
class Solution:
"""
@param nums: A list of integers
@return: A integer indicate the sum of max subarray
"""
def maxSubArray(self, nums):
# write your code here
# 最大子数组的题目有很多,
# 这是比较基础的一个
# 再做一遍
# 动规的思想
# 遍历数组,求以nums[i]为结尾的子数组的最大和
# 那就只需要记录这之前的最小前缀和即可
# prefix_sum记录前i个数的和,
# max_sum记录全局最大值,min_sum记录前i个数中0-k的最小值
if len(nums) == 0:
return 0
prefix_sum = 0
import sys
max_sum, min_sum = -sys.maxsize, 0
for num in nums:
prefix_sum += num
max_sum = max(max_sum, prefix_sum - min_sum)
min_sum = min(min_sum, prefix_sum)
return max_sum
给定一个整数数组,找到长度大于或等于 k 的连续子序列使它们的和最大,返回这个最大的和,如果数组中少于k个元素则返回 0
确保返回结果为整型
k > 0
class Solution:
"""
@param nums: an array of integer
@param k: an integer
@return: the largest sum
"""
def maxSubarray4(self, nums, k):
# write your code here
# 运用前缀和思想
# 应该用动规会时间复杂度好一些,这里先不用
if len(nums) < k:
return 0
prefix_sum = [0]
for i in range(1, len(nums) + 1):
prefix_sum.append(prefix_sum[i - 1] + nums[i - 1])
# 子数组长度大于等于k
import sys
res = -sys.maxsize
for i in range(len(nums) - k + 1):
for j in range(i + k - 1, len(nums)):
res = max(res, prefix_sum[j + 1] - prefix_sum[i])
return res
给定一个整数数组,找出两个 不重叠 子数组使得它们的和最大。
每个子数组的数字在数组中的位置应该是连续的。
返回最大的和。
子数组最少包含一个数
class Solution:
"""
@param: nums: A list of integers
@return: An integer denotes the sum of max two non-overlapping subarrays
"""
def maxTwoSubArrays(self, nums):
# # write your code here
# # 因为两个子数组是不重叠的
# # 所以必定是在某一个位置的两边
# # left[i]记录0-i数组的最大子数组
# # right[i]记录i+1到n-1数组的最大子数组
# # 这样就转化为了求数组的最大子数组问题,41题
# import sys
# res = -sys.maxsize
# for i in range(len(nums)):
# left = self.maxSubArray(nums[:i + 1])
# right = self.maxSubArray(nums[i + 1:])
# res = max(res, left + right)
# return res
# def maxSubArray(self, nums):
# prefix_sum = 0
# import sys
# max_sum, min_sum = -sys.maxsize, 0
# for num in nums:
# prefix_sum += num
# max_sum = max(max_sum, prefix_sum - min_sum)
# min_sum = min(min_sum, prefix_sum)
# return max_sum
# 上述解法的时间复杂度是O(n^2),会超时
# 怎么优化到O(n)呢?
# 还是转化为41题的解法。但是,
# 不嵌套求,分别求出到0到i数组的最大子数组
# i到n-1数组的最大子数组
prefix_sum = 0 # 记录前缀和
import sys
max_sum, min_sum = -sys.maxsize, 0
left_max = [0] * len(nums) # 记录0到i数组的最大子数组和
for i in range(len(nums)):
prefix_sum += nums[i]
# prefix_sum - min_sum表示以nums[i]为结尾的子数组的最大和
max_sum = max(max_sum, prefix_sum - min_sum)
min_sum = min(min_sum, prefix_sum)
left_max[i] = max_sum
prefix_sum = 0
max_sum, min_sum = -sys.maxsize, 0
right_max = [0] * len(nums) # 记录i到n - 1数组的最大子数组和
for i in range(len(nums) - 1, -1, -1):
prefix_sum += nums[i]
# prefix_sum - min_sum表示以nums[i]为起点的子数组的最大和
max_sum = max(max_sum, prefix_sum - min_sum)
min_sum = min(min_sum, prefix_sum)
right_max[i] = max_sum
res = -sys.maxsize
for i in range(len(nums) - 1):
res = max(res, left_max[i] + right_max[i + 1])
return res
给定一个整数数组,找出两个不重叠的子数组A和B,使两个子数组和的差的绝对值|SUM(A) - SUM(B)|∣SUM(A)−SUM(B)∣最大。返回这个最大的差值。
子数组最少包含一个数
class Solution:
"""
@param nums: A list of integers
@return: An integer indicate the value of maximum difference between two substrings
"""
def maxDiffSubArrays(self, nums):
# write your code here
# 因为两个子数组不重叠,所以肯定一个在左边,一个在右边
# 参考两个最大子数组和的问题
# 枚举每个数,找到它左边的最大子数组、最小子数组
# 它右边的最大子数组,最小子数组
# 打擂台获得最大的子数组差值
# if len(nums) == 2:
# return abs(nums[0] - nums[1])
max_diff = 0
for i in range(len(nums) - 1):
leftMaxSubArray = self.maxSubArray(nums[:i + 1])
leftMinAubArray = self.minSubArray(nums[:i + 1])
rightMaxAubArray = self.maxSubArray(nums[i + 1:])
rightMinSubArray = self.minSubArray(nums[i + 1:])
max_diff = max(max_diff, \
abs(leftMaxSubArray - rightMinSubArray), abs(leftMinAubArray - rightMaxAubArray))
return max_diff
def maxSubArray(self, nums):
prefix_sum = 0
import sys
max_sum, min_sum = -sys.maxsize, 0
for num in nums:
prefix_sum += num
max_sum = max(max_sum, prefix_sum - min_sum)
min_sum = min(min_sum, prefix_sum)
return max_sum
def minSubArray(self, nums):
# 用动规来做吧
dp = [0] * len(nums)
dp[0] = nums[0]
for i in range(1, len(nums)):
dp[i] = min(dp[i - 1] + nums[i], nums[i])
return min(dp)
还是会超时。。。
class Solution:
"""
@param nums: A list of integers
@return: An integer indicate the value of maximum difference between two substrings
"""
def maxDiffSubArrays(self, nums):
# write your code here
# 比较典型的动规题目
# 因为两个子数组不重叠,在分割线两边
# 采用枚举分割线的方法
# 维护4个数组,max1, min1, max2, min2
# 分别表示截至到nums[i]且包含nums[i]最大子数组,最小子数组
# 以nums[i]为起点的最大子数组,最小子数组
import sys
max1 = [-sys.maxsize] * len(nums)
min1 = [sys.maxsize] * len(nums)
max1[0] = nums[0]
min1[0] = nums[0]
forward = [(0, 0)] * len(nums)
forward[0] = (nums[0], nums[0])
# prefix_sum = n
for i in range(1, len(nums)):
# prefix_sum += nums[i]
max1[i] = max(max1[i - 1] + nums[i], nums[i])
min1[i] = min(min1[i - 1] + nums[i], nums[i])
forward[i] = (max(max1), min(min1))
max2 = [-sys.maxsize] * len(nums)
min2 = [sys.maxsize] * len(nums)
max2[-1] = nums[-1]
min2[-1] = nums[-1]
backward = [(0, 0)] * len(nums)
backward[-1] = (nums[-1], nums[-1])
for i in range(len(nums) -2, -1, -1):
max2[i] = max(nums[i], nums[i] + max2[i + 1])
min2[i] = min(nums[i], nums[i] + min2[i + 1])
backward[i] = (max(max2), min(min2))
import sys
res = -sys.maxsize
for i in range(0, len(nums) - 1):
res = max(res, \
abs(forward[i][0] - backward[i + 1][1]), abs(forward[i][1] - backward[i + 1][0]))
return res
找出一个序列中乘积最大的连续子序列(至少包含一个数)。
数组长度不超过20000
乘积最大的子序列的积,小于2147483647
class Solution:
"""
@param nums: An array of integers
@return: An integer
"""
def maxProduct(self, nums):
# write your code here
# 典型的动规题目
# 有正有负,需要维护两个数组
# dp1[i]表示计算到nums[i]时的最大值
# dp2[i]表示计算到nums[i]时的最小值
# dp1[i] = dp1[i-1] * nums[i] if nums[i] > 0 else \
# dp2[i-1] * nums[i]
import sys
dp1 = [-sys.maxsize] * len(nums)
dp2 = [sys.maxsize] * len(nums)
dp1[0] = nums[0]
dp2[0] = nums[0]
for i in range(1, len(nums)):
dp1[i] = max(dp1[i - 1] * nums[i], dp2[i - 1] * nums[i], nums[i])
dp2[i] = min(dp1[i - 1] * nums[i], dp2[i - 1] * nums[i], nums[i])
return max(dp1)
给定一个单词列表和一个整数k,求出这个列表中出现频次最高的K个单词。
你需要按照单词的词频排序后输出,越高频的词排在越前面。如果两个单词出现的次数相同,则词典序小的排在前面。
class Solution:
"""
@param words: an array of string
@param k: An integer
@return: an array of string
"""
def topKFrequentWords(self, words, k):
# write your code here
# 先统计每个单词的出现频次
# 将单词按照频次从高到底和词典序排列
hash = {}
for word in words:
if word not in hash:
hash[word] = 1
else:
hash[word] += 1
p = []
for key, value in hash.items():
p.append((value, key))
import functools
p.sort(key=functools.cmp_to_key(self.cmp))
res = []
for i in range(k):
res.append(p[i][1])
return res
def cmp(self, a, b):
if a[0] > b[0]:
return -1
elif a[0] == b[0] and a[1] < b[1]:
return -1
elif a[0] == b[0] and a[1] == b[1]:
return 0
else:
return 1
为网站实现一个负载均衡器,提供如下的 3 个功能:
添加一台新的服务器到整个集群中 => add(server_id)。
从集群中删除一个服务器 => remove(server_id)。
在集群中随机(等概率)选择一个有效的服务器 => pick()。
最开始时,集群中一台服务器都没有。每次 pick() 调用你需要在集群中随机返回一个 server_id。
class LoadBalancer:
def __init__(self):
# do intialization if necessary
# 用列表存储id,用哈希表存储id在列表中对应的index
# add时,在列表中添加id,在哈希表中添加对应的index
# remove时,得到需要remove的id的index,和列表中最后一个id互换
# 同时哈希表中的index也相应修改
# pick时,根据id个数,随机返回一个数,就是index
self.ids = []
self.id2index = {}
"""
@param: server_id: add a new server to the cluster
@return: nothing
"""
def add(self, server_id):
# write your code here
self.ids.append(server_id)
self.id2index[server_id] = len(self.ids) - 1
"""
@param: server_id: server_id remove a bad server from the cluster
@return: nothing
"""
def remove(self, server_id):
# write your code here
index = self.id2index[server_id]
self.id2index[self.ids[-1]] = index
self.ids[index], self.ids[-1] = self.ids[-1], self.ids[index]
self.ids.pop()
"""
@return: pick a server in the cluster randomly with equal probability
"""
def pick(self):
# write your code here
import random
return self.ids[random.randint(0, len(self.ids) - 1)]
给定一个未排序的整数数组,找出最长连续序列的长度。
要求你的算法复杂度为O(n)
class Solution:
"""
@param num: A list of integers
@return: An integer
"""
def longestConsecutive(self, num):
# write your code here
# 遍历数组中的每一个数,找到这个数的最长连续序列
# 有一个技巧是已经形成连续序列的数不用再判断了
num_set = set(num)
maxlength = 1
for x in num:
length = 0
if x in num_set:
length += 1
num_set.remove(x)
right = x + 1
left = x - 1
while right in num_set:
length += 1
num_set.remove(right)
right += 1
while left in num_set:
length += 1
num_set.remove(left)
left -= 1
if maxlength < length:
maxlength = length
return maxlength
假设有一个数组,它的第i个元素是一支给定的股票在第i天的价格。如果你最多只允许完成一次交易(例如,一次买卖股票),设计一个算法来找出最大利润。
class Solution:
"""
@param prices: Given an integer array
@return: Maximum profit
"""
def maxProfit(self, prices):
# write your code here
# 刚开始是没有思路的,看了答案后觉得也很简单
# 不过答案的思路也很巧妙
# 遍历数据,记录股票低点,打擂台记录盈利
import sys
low = sys.maxsize
total = 0
for x in prices:
if x - low > total:
total = x - low
if x < low:
low = x
return total
给定一个数组 prices 表示一支股票每天的价格.
交易次数不限, 不过你不能同时参与多个交易 (也就是说, 如果你已经持有这支股票, 在再次购买之前, 你必须先卖掉它).
设计一个算法求出最大的利润.
class Solution:
"""
@param prices: Given an integer array
@return: Maximum profit
"""
def maxProfit(self, prices):
# write your code here
# 想利润最大的话,就低买高卖
# 遍历价格,如果高于low,并后一天是降低的,就卖出
total_profit = 0
import sys
low = sys.maxsize
for i in range(len(prices)):
if prices[i] > low:
if i + 1 >= len(prices) or (i + 1 < len(prices) and prices[i + 1] < prices[i]):
total_profit += prices[i] - low
low = prices[i + 1] if i + 1 < len(prices) else low
if prices[i] < low:
low = prices[i]
return total_profit
假设你有一个数组,它的第i个元素是一支给定的股票在第i天的价格。设计一个算法来找到最大的利润。你最多可以完成两笔交易。
你不可以同时参与多笔交易(你必须在再次购买前出售掉之前的股票)
class Solution:
"""
@param prices: Given an integer array
@return: Maximum profit
"""
def maxProfit(self, prices):
# write your code here
# 收益最大:最低点买入,最高点卖出
# 也是分成两部分,第一次交易的部分,第二次交易的部分
# 这个和找两个不重叠子数组最大和类似
# dp1[i]表示截止到第i天第一次交易结束的最大收益
# dp2[i]表示第i天以后进行第二次交易的最大收益
# 第一次交易:初始在第0天买入,从第一天顺序遍历
# 第i天价格比最低点低,重新在当天买入
# 第i天价格比最低点高,假设在当天卖出,计算利润
if len(prices) == 0:
return 0
dp1 = [0] * len(prices)
min_price = prices[0]
for i in range(1, len(prices)):
min_price = min(min_price, prices[i])
dp1[i] = max(dp1[i - 1], prices[i] - min_price)
# 第二次交易:初始最后一天卖出,从倒数第二天倒序遍历
# 第i天价格最高点高,重新在这天卖出
# 第i天价格比最高点低,在这天买入,在最高点那天卖出
dp2 = [0] * len(prices)
max_price = prices[-1]
for i in range(len(prices) - 2, -1, -1):
max_price = max(max_price, prices[i])
dp2[i] = max(dp2[i + 1], max_price - prices[i])
import sys
res = -sys.maxsize
for i in range(len(prices)):
res = max(res, dp1[i] + dp2[i])
return res
给一个嵌套的整数列表, 返回列表中所有整数由它们的深度加权后的总和. 每一个元素可能是一个整数或一个列表(其元素也可能是整数或列表)
"""
This is the interface that allows for creating nested lists.
You should not implement it, or speculate about its implementation
class NestedInteger(object):
def isInteger(self):
# @return {boolean} True if this NestedInteger holds a single integer,
# rather than a nested list.
def getInteger(self):
# @return {int} the single integer that this NestedInteger holds,
# if it holds a single integer
# Return None if this NestedInteger holds a nested list
def getList(self):
# @return {NestedInteger[]} the nested list that this NestedInteger holds,
# if it holds a nested list
# Return None if this NestedInteger holds a single integer
"""
class Solution(object):
# @param {NestedInteger[]} nestedList a list of NestedInteger Object
# @return {int} an integer
def depthSum(self, nestedList):
# Write your code here
res = 0
# depth = 1
stack = []
for elem in nestedList:
stack.append((elem, 1))
while stack:
elem, depth = stack.pop()
if elem.isInteger():
res += elem.getInteger() * depth
else:
for elem in elem.getList():
stack.append((elem, depth + 1))
return res
给你一个嵌套的列表,实现一个迭代器将其摊平。
一个列表的每个元素可能是整数或者一个列表。
你不需要实现删除方法
"""
This is the interface that allows for creating nested lists.
You should not implement it, or speculate about its implementation
class NestedInteger(object):
def isInteger(self):
# @return {boolean} True if this NestedInteger holds a single integer,
# rather than a nested list.
def getInteger(self):
# @return {int} the single integer that this NestedInteger holds,
# if it holds a single integer
# Return None if this NestedInteger holds a nested list
def getList(self):
# @return {NestedInteger[]} the nested list that this NestedInteger holds,
# if it holds a nested list
# Return None if this NestedInteger holds a single integer
"""
class NestedIterator(object):
def __init__(self, nestedList):
# Initialize your data structure here.
self.nestedList = nestedList
self.next_elem = None
self.stack = []
for elem in reversed(self.nestedList):
self.stack.append(elem)
# @return {int} the next element in the iteration
def next(self):
# Write your code here
return self.next_elem
# @return {boolean} true if the iteration has more element or false
def hasNext(self):
# Write your code here
while self.stack:
top = self.stack.pop()
if top.isInteger():
self.next_elem = top.getInteger()
return True
else:
for elem in reversed(top.getList()):
self.stack.append(elem)
return False
# Your NestedIterator object will be instantiated and called as such:
# i, v = NestedIterator(nestedList), []
# while i.hasNext(): v.append(i.next())
设计一个迭代器来实现摊平二维向量的功能
class Vector2D(object):
# @param vec2d {List[List[int]]}
def __init__(self, vec2d):
# Initialize your data structure here
self.stack = []
self.next_elem = None
for elem in reversed(vec2d):
self.stack.append(elem)
# @return {int} a next element
def next(self):
# Write your code here
return self.next_elem
# @return {boolean} true if it has next element
# or false
def hasNext(self):
# Write your code here
while self.stack:
top = self.stack.pop()
if isinstance(top, int):
self.next_elem = top
return True
self.stack.extend(top[::-1])
return False
# Your Vector2D object will be instantiated and called as such:
# i, v = Vector2D(vec2d), []
# while i.hasNext(): v.append(i.next())
给出一个表达式 s,此表达式包括数字,字母以及方括号。在方括号前的数字表示方括号内容的重复次数(括号内的内容可以是字符串或另一个表达式),请将这个表达式展开成一个字符串。
数字只能出现在“[]”前面。
class Solution:
"""
@param s: an expression includes numbers, letters and brackets
@return: a string
"""
def expressionExpand(self, s):
# write your code here
# 把所有字符一个一个放到stack里,直到遇到]
# 找到]前面的字符串和重复次数,decode后
# 再放到stack里
stack = []
for c in s:
if c != ']':
stack.append(c)
continue
strs = []
while stack and stack[-1] != '[':
strs.append(stack.pop())
stack.pop() # 去掉[
repeats = 0
base = 1
while stack and stack[-1].isdigit():
repeats += (ord(stack.pop()) - ord('0')) * base
base *= 10
stack.extend(strs[::-1] * repeats)
return ''.join(stack)
给定两个 稀疏矩阵 A 和 B,返回AB的结果。
您可以假设A的列数等于B的行数。