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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

左神讲算法——超级水王问题(详解)

發布時間:2023/12/16 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 左神讲算法——超级水王问题(详解) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文根據左神課程學習總結而來:2021最新左神數據結構算法全家桶

超級水王問題:給你一個數組,出現次數大于數組長度的一半的元素稱之為水王數,怎么能快速找到水王數?

內存限制:時間復雜度O(n),額外空間復雜度O(1)——也就是遍歷數組的次數為有限次,申請的變量數為有限個

方式一:暴力法

暴力法的思想很簡單,用一個hashmap來存放數組中每個元素及其對應的數量,最后遍歷hashmap判斷有無元素數量大于數組長度一半,有則直接返回水王數,否則返回-1

public static int verify(int[] arr) {if (arr == null || arr.length == 0)return -1;//新建hashmap用于存放數組中每個元素及其對應的數量HashMap<Integer, Integer> hashMap = new HashMap<>();//遍歷數組的每個元素for(int num:arr){//如果hashmap中包含該元素,則將該元素的數量+1if(hashMap.containsKey(num))hashMap.put(num,hashMap.get(num)+1);//如果hashmap中不包含key,則將該元素的數量置為1elsehashMap.put(num,1);}//遍歷hashmap中每一個entry<k,v>for(Map.Entry<Integer,Integer> record:hashMap.entrySet()){if(record.getValue()>(arr.length>>1))//這里采用位運算,速度快//返回水王數return record.getKey();}return -1; }

顯然,該方法不符合題目的限制,由于使用了hashmap,所以額外的空間復雜度為O(N)


方法二

如何使用有限變量遍歷有限次數來完成呢?

思路:從數組第一個元素開始,依次刪掉兩個不同的數,最后如果有水王數的話,它會剩下來(反過來不成立,也就是剩下來的數不一定是水王數)

如上圖所示,依次刪除兩個不同的元素,相同則不刪除,最后只剩下3即是水王數

但請注意,剩下的不一定是水王數,比如:12345,刪掉12、34還剩5,但是5不是水王數

這是什么原理呢?我們假設一個數組中有水王數,由于水王數的個數大于所有元素個數的一半,所以如果拿一個非水王數抵消一個水王數,最后還是會剩下水王數;上述刪除不同元素的過程就是如此,還可能會存在兩個非水王數互相抵消的情況,這樣水王數剩下的會更多。

因此我們的算法可以轉換為以下兩步:

  • 依次刪除數組中兩個不同的數
  • 判斷是否有數剩余。如果沒有數剩余,則不存在水王;如果有數剩余,我們再遍歷一次數組,計算該數的真實的出現次數與數組長度的一半進行比較判斷是否為水王數
  • 怎么實現呢?我們只需要兩個變量,變量一candidate作為候選用來存放可能的水王數,變量二hp用來存放其剩余個數,按如下規則遍歷數組:

    • hp=0 代表沒有candidate候選數;hp>0 代表有candidate候選數
    • 如果沒有candidate,則設置當前數賦予candidate,即將當前數作為候選數,hp設置為1
    • 如果有candidate,判斷當前數是否等于candidate,相等則hp+1,不相等則hp-1

    最后判斷看hp是否為0,如果不為0,則代表有可能的水王數,再進行計數判斷即可

    代碼實現

    public static int waterKing(int[] arr) {if (arr == null || arr.length == 0)return -1;int candidate = 0;int hp = 0;for (int cur : arr) {if (hp == 0) {//沒有候選,則將當前數設為候選candidate = cur;hp++;} else if (cur != candidate)//有候選且當前數!=侯選數hp--;else//有候選且當前數=候選數hp++;}//沒有候選數剩余,則沒有水王數if (hp == 0)return -1;//計算候選數在數組中的元素個數int count = 0;for (int num : arr) {if (num == candidate)count++;}//如果候選數元素個數>數組長度的一半則返回,否則返回-1return count > (arr.length >> 1) ? candidate : -1; }

    總結

    以上是生活随笔為你收集整理的左神讲算法——超级水王问题(详解)的全部內容,希望文章能夠幫你解決所遇到的問題。

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