Python LeetCode(八)
不会做
1. Smallest Range
错误思路
class Solution(object):
def smallestRange(self, nums):
"""
:type nums: List[List[int]]
:rtype: List[int]
"""
# 返回两两数组中符合规定范围的值,不断的缩小区间
def min_max_arr(a, b):
mi = max(a[0], b[0])
ma = min(a[len(a)-1], b[len(b)-1])
print mi, ma
return [x for x in sorted(set(a) | set(b)) if x>=mi and x<=ma]
# 计算数组中两两个值构成的区间最小
def min_res(mi):
for i in range(2, len(res)):
if res[i] - res[i-1] < mi[1] - mi[0]:
mi = [res[i-1], res[i]]
elif res[i] - res[i-1] == mi[1] - mi[0] and res[i] < mi[0]:
mi = [res[i - 1], res[i]]
return mi
nl = len(nums)
if nl == 0:
return []
res = nums[0]
for i in xrange(1, nl):
res = min_max_arr(res, nums[i])
print res
rl = len(res)
if rl <= 1:
return res+res
elif rl == 2:
return [res[0], res[1]]
mi = [res[0], res[1]]
return min_res(mi)
炒鸡暴力法
def smallestRange(nums):
minx, miny = 0, 1e9
for i in range(len(nums)):
for j in range(len(nums[i])):
for p in range(len(nums)):
for q in range(j+1 if p == i else 0, len(nums[p])):
x = min(nums[i][j], nums[p][q])
y = max(nums[i][j], nums[p][q])
m, n = 0, 0
while m < len(nums):
n = 0
while n < len(nums[m]):
# 只要该行的数字存在于该区间中,就退出该循环
if x <= nums[m][n] <= y:
break
n += 1
# 遍历到了最后还是没找到,说明该区间不包含该行数据,不是我们想要的
if n == len(nums[m]):
break
m += 1
# 遍历到了最后,说明该区间符合
if m == len(nums):
if miny - minx > y - x or (y - x == miny - minx and minx > x):
minx, miny = x, y
return [minx, miny]
暴力优化法
import bisect
def smallestRange2(nums):
minx, miny = 0, 1e9
for i in range(len(nums)):
for j in range(len(nums[i])):
for p in range(len(nums)):
for q in range(j+1 if p == i else 0, len(nums[p])):
x = min(nums[i][j], nums[p][q])
y = max(nums[i][j], nums[p][q])
m = 0
while m < len(nums):
idx = bisect.bisect_left(nums[m], x)
# 因为是left,所以不可能在最后,同时原插入位置的值也要在区间中,所以只要无法符合该区间,说明数组中不存在该值,立马退出
if idx == len(nums[m]) or nums[m][idx] < x or nums[m][idx] > y:
break
m += 1
if m == len(nums):
if miny - minx > y - x or (y - x == miny - minx and minx > x):
minx, miny = x, y
return [minx, miny]
移动窗口法
def smallestRange3(nums):
minx, miny = 0, 1e9
next = [0] * len(nums)
l = len(nums)
for i in range(l):
for j in range(len(nums[i])):
min_i, max_i = 0, 0
# 找出最大最小值所在的行数
for k in range(l):
if nums[max_i][next[max_i]] < nums[k][next[k]]:
max_i = k
if nums[min_i][next[min_i]] > nums[k][next[k]]:
min_i = k
# 计算最小区间
if miny - minx > nums[max_i][next[max_i]] - nums[min_i][next[min_i]]:
miny = nums[max_i][next[max_i]]
minx = nums[min_i][next[min_i]]
# 移动最小值所在的列数
next[min_i] += 1
# 当最小值的列数到了末尾,则返回
if next[min_i] == len(nums[min_i]):
return [minx, miny]
return [minx, miny]
优先队列
import heapq
def smallestRange4(nums):
pq = [(row[0], i, 0) for i, row in enumerate(nums)]
heapq.heapify(pq)
ans = -1e9, 1e9 # tuple
right = max(row[0] for row in nums) # 所有元素中第一位数的最大值
while pq:
left, i, j = heapq.heappop(pq) # 顺序有讲究,left 放在前面,这样每次都能取出相对最小值
if right - left < ans[1] - ans[0]:
ans = left, right
if j + 1 == len(nums[i]): # 同样的到了数组末尾,表明该行已经处理完了,则返回结果
return ans
v = nums[i][j + 1] # 移动相对最小值的列
right = max(right, v) # 更新相对最大值
heapq.heappush(pq, (v, i, j + 1))
return list(ans)
import collections
def smallestRange6(nums):
"""
:type nums: List[List[int]]
:rtype: List[int]
"""
dmap = collections.defaultdict(set) # 纪录行下标
cover = collections.defaultdict(set) # 纪录每个下标覆盖的数字
nsize = len(nums)
# 数字映射多个下标,因为可能存在多个相同的元素
for idx, nlist in enumerate(nums):
for num in nlist:
dmap[num].add(idx)
# 全部数字
snum = sorted(set(n for nlist in nums for n in nlist))
ssize = len(snum)
start = end = 0
ans = [snum[0], snum[-1]]
gap = 0x7FFFFFFF
while start < ssize and end < ssize:
# end向右移动,把end覆盖的都加入到cover中
while end < ssize and len(cover) < nsize:
for idx in dmap[snum[end]]:
cover[idx].add(snum[end])
end += 1
# 循环保证了start到end之间必然包含了每一行的至少一个元素
# start向右移动,并且删除掉start覆盖的值,从而缩小范围
while start < ssize and len(cover) == nsize:
# cover每一行都存在至少一个数,满足条件可以进行更新
# start不可能追上end,因为要保证每个下标都有值,因此它们会存在一个长度差
if len(cover) == nsize and snum[end - 1] - snum[start] < gap:
gap = snum[end - 1] - snum[start]
ans = [snum[start], snum[end - 1]]
for idx in dmap[snum[start]]:
cover[idx].remove(snum[start])
if not cover[idx]: del cover[idx]
start += 1
return ans
不同的做法
1. Remove Linked List Elements
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def removeElements(self, head, val):
"""
:type head: ListNode
:type val: int
:rtype: ListNode
"""
node = head
while node and node.val != val:
node = node.next
while node:
if node.val == val:
if node.next != None:
node.val = node.next.val
node.next = node.next.next
elif head == node: # 头结点
head = None
break
else: # 尾结点
cur = head
while cur.next and cur.next != node:
cur = cur.next
cur.next = None
break
else:
node = node.next
return head
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def removeElements(self, head, val):
"""
:type head: ListNode
:type val: int
:rtype: ListNode
"""
start = ListNode(0)
start.next = head
prev = start
cur = head
while cur is not None:
if cur.val != val:
prev = cur
cur = cur.next
else:
prev.next = cur.next
cur = prev.next
return start.next
class Solution(object):
def removeElements(self, head, val):
"""
:type head: ListNode
:type val: int
:rtype: ListNode
"""
try:
while head.val == val:
head = head.next
cur = head
nex = cur.next
while nex:
if nex.val != val:
cur.next = nex
cur = cur.next
nex = nex.next
if cur.next.val == val:
cur.next = None
except:
True
return head
2. Reverse Linked List
class Solution(object):
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if head == None:
return None
elif head.next == None:
return head
elif head.next.next == None:
temp = head.next
head.next.next = head
head.next = None
return temp
# 纪录当前结点和下一个结点和下下个结点
node = head
n_node = node.next
nn_node = node.next.next
node.next = None
while node and n_node and nn_node:
n_node.next = node
node = n_node
n_node = nn_node
nn_node = n_node.next
if n_node:
n_node.next = node
return n_node
else:
return node
class Solution(object):
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
pre = None
while head:
cur = head
head = head.next
cur.next = pre
pre = cur
return pre
3. Merge Two Sorted Lists
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
head = ListNode(0)
node = head
while l1 and l2:
if l1.val > l2.val:
node.next = l2
l2 = l2.next
elif l1.val < l2.val:
node.next = l1
l1 = l1.next
else:
node.next = l1
l1 = l1.next
node = node.next
node.next = l2
l2 = l2.next
node = node.next
if l1:
node.next = l1
elif l2:
node.next = l2
return head.next
class Solution(object):
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
dummy = current = ListNode(0)
while l1 and l2:
if l1.val < l2.val:
current.next = l1
l1 = l1.next
else:
current.next = l2
l2 = l2.next
current = current.next
current.next = l1 if l1 else l2
return dummy.next
class Solution(object):
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
if not l1:
return l2
elif not l2:
return l1
head = None
if l1.val > l2.val:
head = l2
head.next = self.mergeTwoLists(l1, l2.next)
else:
head = l1
head.next = self.mergeTwoLists(l1.next, l2)
return head
关注公众号:数据结构与算法那些事儿,每天一篇数据结构与算法

浙公网安备 33010602011771号