数据结构与算法--查找与排序另类用法-旋转数组中的最小数字
生活随笔
收集整理的這篇文章主要介紹了
数据结构与算法--查找与排序另类用法-旋转数组中的最小数字
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
查找與排序
查找
- 查找與排序都在程序設計中常被用到的算法。查找相對而言簡單,一般都是順序查找,二分查找,哈希表查找,和二叉排序樹查找。其中二分查找是我必須熟悉的一種。
- 哈希表和二叉排序樹主要點在于他的數據結構而不是算法。哈希表主要的優點是我們利用他能在O(1)的時間查找某個元素,是效率最高的查找方式。但是缺點是需要額外空間來實現哈希表
- 二叉排序樹查找算法對應的數據結構是二叉搜索樹(或者叫二叉查找樹),之前我們已經著重討論過這種數據結構原理以及自己的實現。
排序
- 排序比查找要復雜,例如經常選擇一種排序算法的時候經常會對各種排序算法進行比較:插入排序,冒泡排序,歸并排序,快速排序等不同算法的優劣。而這些都是必須掌握的排序算法,我們必須能從空間福再度,時間復雜度等方面去分析他們的優缺點。其中快速排序是重中之重。可見的幾種排序算法在之前的章節中也用動圖的方式給出來詳細的解釋,實現。
實際案例
- 快排是重要的排序算法,但是在具體場景下我們需要選擇最優最合適的算法,例如下情況:
- 實現一個排序算法,實際復雜度,空間復雜度必須不超過O(n),對公司所有員工年齡進行排序。
- 分析上題中,重點空間復雜度,實際復雜度O(n)
- 排序對象,員工年齡,我們假設員工都是100 歲以下,量級也不大,一個公司最多 也就10萬
- 這種情況,數組區間范圍是固定的,而且基數不大最理想的排序算法是計數排序
另類用法:旋轉數組中的最小數字
- 題目:將數組最開始的若干個元素搬到數組的末尾,我們稱為數組的旋轉。輸入一個遞增數組的旋轉,輸出旋轉數組的最小元素,例如數組{3,4,1,5,1,2}是{1,2,3,4,5}的一個旋轉,明顯最小值是1,
分析
-
直觀來看找最小值一次遍歷就能搞定,時間復雜度O(n),但是這個并沒有利用這個數組的特性,已排序,旋轉后兩部分有序肯定有更優解
-
旋轉后,兩部分數組都有序,并且遞增,必然有序部分后面大于前面
-
然后分界處必然是最小值的特點
-
由上部分分析我們自然想到二分查找尋找最小值。
-
流程如下:
- 定義指針min,max分別指向數組兩端,按題意,第一個元素應該大于等于 最后一個元素,因為旋轉過。
- 接著找中間元素mid =(max+ min)/2, 如果中間元素大于min,則min到mid之間處于遞增,則最小值必然在中間元素后面
- 此時我們將min指針移動到mid位置
- 同樣如果中間元素mid 小于min,則表示最小值在mid或者mid的左邊,
- 此時我們將max指針移動到mid位置
- 依次對min,max之間的數組部分進行如上流程,直到 max - min = 1 為止,此時最大,最小是相鄰,則找出最小值
-
如下實際案例{3,4,5,1,2},
- min指針指向第0個元素 3 ,max指向最后一個2,中間元素5
- 5 > 3,min移動到mid位置,也就是min指向5
- 再次,中間元素變為1,1<5,此時,最小值在min右邊
- 將max移動到mid位置,也就是max指向1 ,
- 此時max - min = 1,得到最小值max位置。
代碼實現
/*** @author liaojiamin* @Date:Created in 11:39 2021/3/16*/ public class FindRotateMin {public static int findMin(int[] array){if(array == null || array.length <= 0){return -1;}if(array.length == 1){return array[0];}if(array.length == 2){return array[0]> array[1] ? array[0] : array[1];}int index1 = 0;int index2 = array.length -1;int indexMin = index1;while (array[index1] >= array[index2]){if(index2 - index1 == 1){indexMin = index2;break;}indexMin = (index2 + index1)/2;if(array[indexMin] >= array[index1]){index1 = indexMin;}else if(array[indexMin] <= array[index1]){index2 = indexMin;}}return indexMin;}public static void main(String[] args) {int[] array = {3,4,5,0,1,2};System.out.println(array[findMin(array)]);} }- 問題:上述代碼中我們每次判斷都會有等于的情況,當index1, index2,兩個相同的時候,并且他們中介的數字indexMin也相同,這個時候,我們符合第一個判斷,將indexMin賦值給了index1,此時默認最小數字在后面,其實不一定對,如下反例
- 數組{1,0,1,1,1} 和數組{1,1,1,0,1} 都可以看成遞增排序{0,1,1,1,1}的旋轉,但是下圖中最小值分別在左邊和右邊:
- 如上情況,首尾數字,中介位置數字都是1 ,但是卻有兩種不同的最小值位置,因此這種特殊情況:當兩個指針數字以及中間數字都一樣的時候,無法判斷最小值的位置,我們不得不采取遍歷的方式。
- 修改代碼如下
測試用例
- 輸入旋轉數組,數組中沒有重復數字
- 邊界值測試,只有一個,兩個數字的數組
- 輸入特殊null值
- 輸入重復數字的數組
上一篇:數據結構與算法–利用棧實現隊列
下一篇:數據結構與算法–再談遞歸與循環(斐波那契數列)
總結
以上是生活随笔為你收集整理的数据结构与算法--查找与排序另类用法-旋转数组中的最小数字的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ipad电池健康度怎么看 ipad怎么看
- 下一篇: 数据结构与算法--再谈递归与循环(斐波那