日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构与算法-- 数组中出现次数超过一半的数字(时间复杂度的讨论)

發布時間:2023/12/4 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构与算法-- 数组中出现次数超过一半的数字(时间复杂度的讨论) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

時間效率

  • 互聯網想對時間效率格外的敏感,所以我們總是在需求迭代一定程度后去做優化。而且我們解決問題的時候,時間效率往往是一個考查的重點。因此我們平時編碼過程中就必須不斷的優化效率,追求完美的態度與能力。
    • 首先是編碼習慣,例如java中字符串操作我們不建議使用String的+ 運算符來完成。這樣會產生非常多的String臨時變量,造成空間與實際的浪費,更好的方式是用StringBuilder的Append方法完成字符串的拼接。
    • 其次,即使是同一個算法用循環和遞歸兩種思路實現時間效率也是不一樣的。遞歸的本質是吧一個大的復雜問題拆解成兩個或者多個小的簡單問題,如果小問題中互相重疊,那么直接用遞歸實現,代碼會更加簡單,但是時間效率非常差,這時候,我們可以用遞歸的思路來分析,但是用數組(一維數組或者二維數組)來保存中間結果基于循環實現。絕大部分動態規劃算法的分析和代碼實現都是分這兩個步驟。
    • 再次,代碼時間效率還體現在我們數據結構的掌握程度。
    • 最后以如下提來舉例:

數組中出現次數超過一半的數字

  • 數組中有一個數字出現的次數超過數組長度的一半,找出這個數字,例如:輸入一個長度為10 的數組{1,2,3,3,3,3,3,3,4,5,6,7}。由于數組3在數組中出現了6次,超過數組長度的一半因此輸出3

  • 解法一:看到題目的第一反應就是講數組排序統計,自然很容易得出每個數字的次數。題目給出的數組沒說排序

    • 先排序。排序的時間復雜度O(nlogn)
    • 接著統計O(n)
    • 最直觀的算法通常不是最優解,我們接著找更優的解法
  • 解法二:題意中是一個特殊的數組,數組中有一個數字出現次數超過數組長度的一半。排序后,不管其中重復的數字怎么排,其中位于數組中間位置的數字比如就是出現超過一半的那個數字。

    • 結論是我們需要找的就是統計學中的中位數。即長度為n 的數組,找出第n/2 大的數字,這個有成熟的O(N)算法得到數組中第K個大的數
  • 分析:

    • 我們在之前的排序算法文章:數據結構與算法–排序算法總結(動圖演示) 對各種排序算法有詳細的解釋。根據快排的思路,我們先選擇數組中一個隨機的數字,然后調整數組中數字順序,使得左邊小,右邊大。如果這個數字的下標正好是n/2,那么得到我們的結果
    • 如果下標大于n/2,那么中位數在 左邊,則同樣的算法用在左邊的數列上
    • 如果下標小于n/2,那么中位數在右邊,則同樣的算法用在作右邊的數列上
    • 典型的遞歸
  • 經過如上分析有如下代碼:

/*** 如果數組中超過數組一半的數都是同一個數,找出那個數字* @author liaojiamin* @Date:Created in 17:21 2021/5/27*/ public class MoreThenHalfNum {public static void main(String[] args) {int[] arrayData = {4,4,4,4,4,4,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6};System.out.println(findMiddleNum(arrayData, 0, arrayData.length -1));}/*** 方法一:二分查找思想找出 數組中間大小的那個數字* 如果該數字在數組中的個數超過數組的一半,那么中間大小的數字必然是這個數字* */public static int findMiddleNum(int[] arrayData, int left, int right){if(arrayData == null || arrayData.length <= 1){return -1;}Integer middle = (left + right)/2;if(left < right){int index = swapArray(arrayData, left, right);if(index == middle){return arrayData[middle];}quickSort(arrayData, left, index - 1);quickSort(arrayData, index + 1, right);}return arrayData[middle];}/*** 挖坑法二分查找* */public static int swapArray(int[] arrayData, Integer left, Integer right){if(left < right){int position = arrayData[left];while (left < right){while (right > left && arrayData[right] > position){right --;}if(left < right){arrayData[left] = arrayData[right];left ++;}while (left < right && arrayData[left] < position){left ++;}if(left < right){arrayData[right] = arrayData[left];right--;}}arrayData[left] = position;}return left;} }
  • 以上解法時間復雜度能達到O(n),但是還是有點復雜的,可能你寫不出來,是否有更簡單的方法?

  • 解法三:依然分析數組的特性,超過一半的存有量,也就是他比他的數字出現的次數的總和還要多,

    • 那么我們只需要統計個數就能得到了
    • 只進行一次遍歷數組,保存兩個值,一個數組中數字,一個他的次數
    • 如果遍歷到下一個數據的時候,還是這個數,那么次數加 +1,否則次數 -1
    • 如果次數達到0 ,那么情況保存的這個數,在接著遍歷依然用以上邏輯
    • 由于我們要找的數據出現的次數比其他數字總和還要多,那么肯定最后一個保存下來的數據必然是我們要的那個出現此處過半的數據。
  • 根據如上分析有如下代碼:

/*** 如果數組中超過數組一半的數都是同一個數,找出那個數字* @author liaojiamin* @Date:Created in 17:21 2021/5/27*/ public class MoreThenHalfNum {public static void main(String[] args) {int[] arrayData = {4,4,4,4,4,4,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6};System.out.println(findThenHalfNum(arrayData));}/*** 方法二:依次遍歷數組中每一個數字,將遇到的數字保存到 k 對象中,如果依次遇到的數字中與k中相同統計+1* 否則 -1,如果統計為0 情況k對象,依次對每個數字操作,最終保留下來的比如是數量最多的那個數字* */public static int findThenHalfNum(int[] arrayData){if(arrayData == null || arrayData.length <= 1){return -1;}int findNum = -1;int findNumCount = -1;for (int i = 0; i < arrayData.length; i++) {if(findNum == -1){findNum = arrayData[i];findNumCount = 1;}else {if(findNumCount == 0){findNum = arrayData[i];findNumCount =1;}else {if(findNum == arrayData[i]){findNumCount ++;}else {findNumCount --;}}}}return findNum;}}
  • 如上第二第三都是最優解,但是第二中修改了數組,第三種沒有修改數組,可以依據具體情況來決定方案。

上一篇:數據結構與算法-- 八皇后問題(兩種實現方案)
下一篇:數據結構與算法–將數組排成最小的數

總結

以上是生活随笔為你收集整理的数据结构与算法-- 数组中出现次数超过一半的数字(时间复杂度的讨论)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。