1. 程式人生 > >劍指offer系列(十三)陣列中的逆序對,兩個連結串列的第一個公共結點,數字在排序陣列中出現的次數

劍指offer系列(十三)陣列中的逆序對,兩個連結串列的第一個公共結點,數字在排序陣列中出現的次數

陣列中的逆序對

題目描述

在陣列中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個陣列中的逆序對的總數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)