剑指offer系列(十四)数组中的逆序对,两个链表的第一个公共结点,数字在排序数组中出现的次数

本文深入探讨了数组中逆序对的计算方法,包括归并排序优化算法,以及寻找两个链表第一个公共结点的巧妙解决方案。同时,提供了统计排序数组中特定数字出现次数的有效算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数组中的逆序对

题目描述

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007

输入描述:

题目保证输入的数组中没有的相同的数字

数据范围:

对于%50的数据,size<=10^4

对于%75的数据,size<=10^5

对于%100的数据,size<=2*10^5

解题思路:

法一:(未通过)

先将原序列排序,然后从排完序的数组中取出最小的,它在原数组中的位置表示有多少比它大的数在它前面,每取出一个在原数组中删除该元素,保证后面取出的元素在原数组中是最小的,这样其位置才能表示有多少比它大的数在它前面,即逆序对数。

法二:(通过)

用归并排序,归并排序能够有效的减少最坏时间复杂度,但是它有额外的开销,以空间换时间。把原数据分成两个数组,每次取两个数组中的最小值放入一个新的数组中,直到其中一个数组全部取完。

代码:

法一:

# -*- coding:utf-8 -*-
class Solution:
    def InversePairs(self, data):
        # write code here
        copy =[]
        count =0
        for i in data:
            copy.append(i)
        copy.sort()
        
        for i in range(len(copy)):
            count += data.index(copy[i])
            data.remove(copy[i])
            
        return count %1000000007
                       

法二:

# -*- coding:utf-8 -*-
class Solution:
    def InversePairs(self, data):
        # write code here
        length = len(data)
        if data == None or length <=0:
            return 0
        copy = [0]*length
        for i in range(length):
            copy[i] = data[i]
            
        count = self.InversePairsCore(data,copy,0,length-1)
        return count%1000000007
    def InversePairsCore(self, data, copy, start, end):
        if start == end:
            copy[start] = data[start]
            return 0
        length = (end-start)//2
        left = self.InversePairsCore(copy, data, start, start+length)
        right = self.InversePairsCore(copy, data, start+length+1, end)
        i = start +length
        j = end
        
        indexCopy = end
        count = 0
        while i >=start and j>=start+length+1:
            if data[i]>data[j]:
                copy[indexCopy] = data[i]
                indexCopy -=1
                i -= 1
                count +=j-start-length
            else:
                copy[indexCopy]=data[j]
                indexCopy -= 1
                j -=1
        while i>=start:
            copy[indexCopy] = data[i]
            indexCopy-=1
            i-=1
        while j>=start+length+1:
            copy[indexCopy] = data[j]
            indexCopy -= 1
            j-=1
        
        return left+right+count
        

两个链表的第一个公共结点

题目描述

输入两个链表,找出它们的第一个公共结点。

解题思路:(真的很奇妙~)

共同节点,意味着从共同节点开始之后所有的节点数都是相同的,这是链表,只要有一个共同节点,那么之后所有的指向
也是重复的。

先依次遍历两个链表,记录两个链表的长度m和n,如果 m > n,那么我们就先让长度为m的链表走m-n个结点,然后两个链表同时遍历,当遍历到相同的结点的时候停止即可。对于 m < n,同理。

代码:

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def FindFirstCommonNode(self, pHead1, pHead2):
        # write code here
        Length1 = self.GetLength(pHead1)
        Length2 = self.GetLength(pHead2)
        LengthDiff = abs(Length1- Length2)
        
        if Length1>Length2:
            pHeadLong = pHead1
            pHeadShort = pHead2
        else:
            pHeadLong = pHead2
            pHeadShort = pHead1
            
        for i in range(LengthDiff):
            pHeadLong = pHeadLong.next
        while pHeadLong != None and pHeadShort != None and pHeadLong != pHeadShort:
            pHeadLong = pHeadLong.next
            pHeadShort = pHeadShort.next
        return pHeadLong
    def GetLength(self, pHead):
        length = 0
        while pHead:
            pHead = pHead.next
            length += 1
        return length

数字在排序数组中出现的次数

题目描述

统计一个数字在排序数组中出现的次数。

解题思路:

法一:count函数是顺序查找,最坏时间复杂度是O(n)

法二:

看见有序就要想起使用二分法查找,最坏时间复杂度是O(logn)

对于一个有序数组,要考虑 1,2,2,2,3,4这种情况,计算k=2在数组中出现的次数,用二分法去找这个数,一个找最前面
出现的2的下标,一个找最后面2出现的小标,这样前后相减+1即可得到结果。
 

代码:

法一:

# -*- coding:utf-8 -*-
class Solution:
    def GetNumberOfK(self, data, k):
        # write code here
        return data.count(k)

法二:

# -*- coding:utf-8 -*-
class Solution:
    def GetNumberOfK(self, data, k):
        # write code here
        number = 0
        if data != None and len(data)>0:
            length = len(data)
            First = self.GetFirst(data, length, k,0,length-1)
            Last = self.GetLast(data, length, k, 0, length-1)
            if First > -1:
                number = Last-First +1
        return number
    def GetFirst(self, data, length, k, start, end):
            if start > end:
                return -1
            middle = (start+end)//2
            if data[middle]==k:
                if middle>0 and data[middle-1]==k:
                    end = middle-1
                else:
                    return middle
            elif data[middle]>k:
                end = middle-1
            else:
                start = middle+1
            return self.GetFirst(data, length, k, start, end)
    def GetLast(self, data, length, k, start, end):
        if start> end:
            return -1
        middle = (start+end)//2
        if data[middle]==k:
            if middle<end and data[middle+1]==k:
                start = middle+1
            else:
                return middle
        elif data[middle]>k:
            end = middle-1
        else:
            start = middle+1
        return self.GetLast(data, length, k, start, end)
        

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值