翻转单词顺序列
- 问题描述:牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?
- 解题思路:无fa可说
class Solution:
def ReverseSentence(self, s):
return ' '.join(s.split(' ')[::-1])
数组中的逆序对
- 问题描述:给一个数组,求数组中的逆序对
- 解题思路:归并排序的经典应用,取模运算开销不小,如果在递归函数中取模,会超时。但是归并排序这种分解子问题的副作用是,存在与问题规模相关的额外操作,递推公式为 InversePairs(n) = InversePairs(0:mid)+ InversePairs(mid:n) + Merge(0:n), 副作用在Merge(0:n)项,这个归并操作的必要性来自于求解的递推关系,对于本题,可以改变递推关系为InversePairs(n) = InversePairs(n-1) + FindInverse(n),也就是当前问题最优=子问题最优+当前问题增加的一项后的增加的逆序数,求解当前问题增加一项后的增加的逆序数,关键在如何避免重复,否则与O(n^2)的暴力求解等价。前缀和满足这一要求,于是考虑使用为前缀和特化的树状数组解决本问题。但是对于大量数据,用桶来完成树状数组不现实,就需要做点映射,此时需要排序,开销大于归并办法。
class Solution:
def InversePairs(self, data):
def inverse_count(d, s, e):
if e - s <= 1:
return 0
if e - s == 2:
if d[s] > d[e - 1]:
d[s], d[e - 1] = d[e - 1], d[s]
return 1
else:
return 0
m = (s + e) // 2
res = inverse_count(d, s, m) + inverse_count(d, m, e)
i, j = s, m
tmp = []
while i < m and j < e:
if d[i] > d[j]:
res += m - i
tmp.append(d[j])
j += 1
else:
tmp.append(d[i])
i += 1
if i < m:
tmp += d[i:m]
if j < e:
tmp += d[j:e]
d[s:e] = tmp
return res
return inverse_count(data, 0, len(data))%1000000007
from functools import reduce
def qsort_not_inplace(data):
if not data: return data
arr = data[:]
stack = list()
stack.append((0, len(arr)))
while stack:
start, end = stack.pop()
if start + 1 >= end:
if end>start+1 and arr[start] > arr[end-1]:
arr[start],arr[end-1] = arr[end-1],arr[start]
continue
pivot = arr[start]
i, j = start+1, end - 1
while i < j:
while i < j and arr[i] < pivot: i += 1
while i < j and arr[j] >= pivot: j -= 1
if i < j: arr[i], arr[j] = arr[j], arr[i]
arr[start], arr[i - 1] = arr[i - 1], pivot
stack.append((start, i))
stack.append((i, end))
return arr
def low_bit(n):
return n & (-n)
class TreeArray:
def __init__(self, data):
self.__size = len(data)
self.__arr = [0 for _ in data] + [0]
self.__mapping = dict(
(str(num), idx+1) for idx, num in enumerate(qsort_not_inplace(data)))
def __getitem__(self, idx):
return self.__arr[self.__mapping[str(idx)]]
def __setitem__(self, idx, val):
self.__arr[self.__mapping[str(idx)]] = val
def __len__(self):
return self.__size
def update(self, idx, val=1):
idx = self.__mapping[str(idx)]
while idx < self.__size+1:
self.__arr[idx] += val
idx += low_bit(idx)
def prefix_sum(self, idx):
idx = self.__mapping[str(idx)]
if not idx:
return self.__arr[0]
acc_sum = 0
while idx:
acc_sum += self.__arr[idx]
idx -= low_bit(idx)
return acc_sum
class Solution:
def InversePairs(self, data):
tree_arr = TreeArray(data)
inverse_num = 0
for i in range(len(tree_arr)):
tree_arr.update(data[i])
inverse_num += i+1 - tree_arr.prefix_sum(data[i])
return inverse_num%1000000007
翻转链表
- 问题描述:输入一个链表,反转链表后,输出新链表的表头。
- 解题思路:单链表,翻转,最自然的逻辑是递归,分解出子问题,翻转两个已翻转好的部分。
class Solution:
def ReverseList(self, head):
def reverse(pre,cur):
if not cur:
return None
if not cur.next:
cur.next = pre
return cur
tp = cur.next
cur.next = pre
return reverse(cur,tp)
return reverse(None,head)