剑指offer: 翻转单词顺序列,数组中的逆序对, 翻转链表

翻转单词顺序列


  • 问题描述:牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?
  • 解题思路:无fa可说
# -*- coding:utf-8 -*-
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)的暴力求解等价。前缀和满足这一要求,于是考虑使用为前缀和特化的树状数组解决本问题。但是对于大量数据,用桶来完成树状数组不现实,就需要做点映射,此时需要排序,开销大于归并办法。
# Version: Merge Sorting Variation
# -*- coding:utf-8 -*-
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
# version: Prefix Sum using TreeArray
# warning: not optimized
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

翻转链表


  • 问题描述:输入一个链表,反转链表后,输出新链表的表头。
  • 解题思路:单链表,翻转,最自然的逻辑是递归,分解出子问题,翻转两个已翻转好的部分。
# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    # 返回ListNode
    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)

猜你喜欢

转载自blog.csdn.net/qq_35279914/article/details/82254526