給定兩個大小為 m 和 n 的正序(從小到大)陣列 nums1 和 nums2。
請你找出這兩個正序陣列的中位數,並且要求演算法的時間複雜度為 o(log(m + n))。
你可以假設 nums1 和 nums2 不會同時為空。
分析
單看題目尋找中位數而言,可以簡化為尋找兩個數列中的第n位數字,可以通過利用指標,對於兩個數列中大小比較的,直至找到最中間的乙個數或兩個數,由於要求時間複雜度為o(log(m + n)),可以得知題主可能想使用要用到二分法尋找指定數,如果拋去時間複雜度這個附加條件,我們可以用一種比較簡單和粗暴的解法來判斷。
1.合併為乙個數列
這個解法比較簡單,將兩個數列合併到乙個數列中去,然後排序,若數列長度 m+n 為奇數,則 (n+m)/2 的位置即為中位數,若為偶數,則為中間兩位數的和的二分之一,具體**如下
func
findmediansortedarrays
(nums1 [
]int
, nums2 [
]int
)float64
sort.
ints
(nums1)if(
len(nums1)-1
)%2==
0else
}`
在這個**中,使用的是sort包,具體源**如下,使用的是快速排序的方法
type inte***ce inte***ce
/ sort sorts data.
// it makes one call to data.len to determine n, and o(n*log(n)) calls to
// data.less and data.swap. the sort is not guaranteed to be stable.
func
sort
(data inte***ce)
maxdepth *=
2quicksort
(data,
0, n, maxdepth)
}
所以用這種方法的時間複雜度為 o(m+n),空間複雜度也為 o(m+n),
2.不合併為乙個陣列,簡化空間複雜度直接兩個數列進行比較,當比較出大小時,指標則向後移動一位,並將此值賦予輸出值,這種方法麻煩在於,什麼時候移動a組數列的指標,什麼時候移動b組數列的指標,奇偶的時候如何劃分,當數列總長度為奇數的時候,我們只需要取中間第k次的數值即可,當為偶數的時候,我們則需要上一次的輸出結果,所以我們還需要一位數儲存上一次的輸出結果。
具體**如下:
func
findmediansortedarrays
(nums1 [
]int
, nums2 [
]int
)float64
else
}if s%2!=
0else
}
這種方法同樣繁瑣,尤其是要考慮指標移動時,可能超出數列長度的問題,因為仍然經歷了兩個數列,所以時間複雜度依舊為o(m+n), 空間複雜度為o(1),因為只有幾個特定值
3. 二分查詢
二分查詢可以大批量的解決掉運算複雜的問題,每一次的計算可以減下一半的計算量,在這道題中,可以簡化為不斷尋找中位數進行比較,具體原理如下。
首先,既然時間複雜度為o(log(m+n)),所以必然是將兩個數列看做是同乙個數列,再用二分法計算一半的量,假如有十乙個數列,我們可以嘗試分解他的解題思路。
首先,正如前面所說,本題的實質就是在找第k個最小數,則我們可以用二分法逐漸逼近第 k 小的數字來實現演算法,則可以把兩組數列中 k/2 個數字相比較,來去掉最小的兩個數。我們可以直接比較a[k/2]和b[k/2],若a[k/2]func
findmediansortedarrays
(nums1 [
]int
, nums2 [
]int
)float64
else
return0}
func
getkth
(nums1 [
]int
, n int
, nums2 [
]int
, m int
, k int
)int
if n ==
0if k ==
1 i :=
min(k/
2,n)
if nums1[i-1]
> nums2[i-1]
else
}func
min(x, y int
)int
return y
}
func
findmediansortedarrays
(nums1 [
]int
, nums2 [
]int
)float64
else
return0}
func
getkthelement
(nums1, nums2 [
]int
, k int
)int
if index2 ==
len(nums2)
if k ==
1 half := k/
2 newindex1 :=
min(index1 + half,
len(nums1))-
1 newindex2 :=
min(index2 + half,
len(nums2))-
1 pivot1, pivot2 := nums1[newindex1]
, nums2[newindex2]
if pivot1 <= pivot2
else
}return0}
func
min(x, y int
)int
return y
}
時間複雜度為o(log(m+n)),也可以嘗試兩個數列分別取中位數然後比較的方法,時間複雜度為o(logm*n)。 每日一題 leetcode 162 尋找峰值
尋找峰值 難度中等243 峰值元素是指其值大於左右相鄰值的元素。給定乙個輸入陣列 nums,其中 nums i nums i 1 找到峰值元素並返回其索引。陣列可能包含多個峰值,在這種情況下,返回任何乙個峰值所在位置即可。你可以假設 nums 1 nums n 示例 1 輸入 nums 1,2,3,...
每日一題 LeetCode
在陣列中的兩個數字,如果前面乙個數字大於後面的數字,則這兩個數字組成乙個逆序對。輸入乙個陣列,求出這個陣列中的逆序對的總數。示例 1 輸入 7,5,6,4 輸出 5 限制 0 陣列長度 50000 思想是 分治演算法 所有的 逆序對 於 3 個部分 左邊區間的逆序對 右邊區間的逆序對 橫跨兩個區間的...
LeetCode每日一題(題1028)
最近在刷leetcode每日一題,每次做完之後總能有些收穫,所以想著不如每天寫個部落格記錄一下做的題目的解法以及自己寫的時候問題出在 從先序遍歷還原二叉樹 題目大意 給出乙個字串 1 2 3 4 5 6 7 1代表節點的值,前面的 個數代表節點的深度。如果只有乙個子節點,保證這個節點為左子節點。返回...