劍指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)