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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

算法--微软面试:指定数字在数组中出现的次数

發布時間:2025/3/20 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法--微软面试:指定数字在数组中出现的次数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Q題目

在排序數組中,找出給定數字的出現次數,比如 [1, 2, 2, 2, 3] 中2的出現次數是3次。

Answer解法

這道題要求出結果不難,但要求最有解的話,就需要花費一番功夫了。常見解法有如下四種:

定義: 要查詢的數字為key 查詢的數組為arr

1)暴力窮舉

直接從頭遍歷計數就可以了

2)遍歷開始和最后一次出現的index

  • 從前開始遍歷,遇到與key相同,則停止遍歷,得到startIndex

  • 從后開始遍歷,遇到與key相同,則停止遍歷,得到endIndex

  • 數字出現次數為:endIndex-startIndex

該做法比方法一好一些,減少了一部分計算次數


方法一和方法二代碼如下:

package 微軟面試題數字次數;import java.util.Arrays; import java.util.HashSet;public class Test1 {public static void main(String[] args) {int[] arr={1,3,7,7,7,7,8,9,9,10};System.out.println("方法一測試:不存在key--"+getNumTimes(arr, 11));System.out.println("方法一測試:存在一個key--"+getNumTimes(arr, 3));System.out.println("方法一測試:存多個key--"+getNumTimes(arr, 9));System.out.println();System.out.println("方法二測試:不存在key--"+getNumTimes2(arr, 11));System.out.println("方法二測試:存在一個key--"+getNumTimes2(arr, 3));System.out.println("方法二測試:存多個key--"+getNumTimes2(arr, 9));}//方法一:暴力解法--完整遍歷public static int getNumTimes(int[] arr,int key){int count=0;//超出arr的最大值和最小值就沒必要遍歷了if(key>=arr[0]&&key<=arr[arr.length-1]){for (int i : arr) {if(i==key){count++;}}}return count;}//方法二:遍歷出開頭和結尾public static int getNumTimes2(int[] arr,int key){int count=0;//key出現的次數int start=-1;//key第一次出現的位置--索引有index=0,所以這里用-1int end=-1;//key最后一次出現的位置//超出arr的最大值和最小值就沒必要遍歷了if(key>=arr[0]&&key<=arr[arr.length-1]){//計算startfor (int i = 0; i < arr.length; i++) {if(arr[i]==key){start=i;break;}}}//計算end--若start為最后一個元素或key(即start=-1)不存在時,沒必要求end了if(start!=-1 && start<arr.length-1){for(int i=arr.length-1;i>=0;i--){if(arr[i]==key){end=i;break;}}count=Math.abs(end-start+1);}return count;}}

運行結果:


3)二分法查找所有數字

直接使用二分法去查找所有出現的值,相對于前兩種計算次數少一些

代碼如下:

package 微軟面試題數字次數;public class Test2 {//方法三:二分法查找//參數:arr--查找的數組 key--要查找的數字 // startIndex和endIndex為在數組arr中的查找范圍--startIndex:起始下標 endIndex:截止下標static int count=0;public static void getNumTimes4ByBinary(int[] arr, int key, int startIndex,int endIndex){int middle=(startIndex+endIndex)/2;if(startIndex>endIndex){return;//輸入的參數不合法}if(arr[middle]==key){count++;//向前找getNumTimes4ByBinary(arr, key, startIndex, middle-1);//向后找getNumTimes4ByBinary(arr, key, middle+1, endIndex);}else if (arr[middle]<key) {getNumTimes4ByBinary(arr, key, middle+1, endIndex);}else {getNumTimes4ByBinary(arr, key, startIndex, middle-1);}}public static void main(String[] args) {int[] arr={1,3,7,7,7,7,8,9,9,10};getNumTimes4ByBinary(arr, 7, 0 , arr.length-1);System.out.println("方法三測試:存在多個key--"+count);}}

注意:count為static變量,所以測試時,只能分別測試三種情況


4)二分法查找和for循環結合

  • 使用二分法查找數字,查詢到第一個key后馬上結束

  • 根據key的下標向前和向后遍歷,直到與key不相同為止,獲得count

與前三種方法相比,大大減少了計算的次數,不過這還不是最佳算法

代碼如下:

package 微軟面試題數字次數;import java.util.Arrays; import java.util.HashSet;public class Test1 {public static void main(String[] args) {int[] arr={1,3,7,7,7,7,8,9,9,10};System.out.println();System.out.println("方法三測試:不存在key--"+getNumTimes3(arr, 11));System.out.println("方法三測試:存在一個key--"+getNumTimes3(arr, 3));System.out.println("方法三測試:存多個key--"+getNumTimes3(arr, 9));}//方法三:二分法 --先二分法查找判斷是否存在key,并獲得索引public static int getNumTimes3(int[] arr,int key){int count=0;//超出arr的最大值和最小值就沒必要遍歷了if(key>=arr[0]&&key<=arr[arr.length-1]){//判斷有沒有keyint index=Arrays.binarySearch(arr, key);if(index>=0){//存在key值//向前找for(int i=index;i>=0;i--){if(arr[i]!=key){break;}count++;}//向后找for(int i=index+1;i<arr.length;i++){if(arr[i]!=key){break;}count++;}}}return count;}}

運行結果如下:


5)二分法查找開始和結束index

使用二分法查詢開始和結束的index,關鍵是邊界問題的判斷。

開始邊界:與前一個數字比較,若不相同則是邊界

結束邊界:與后一個數字比較,若不相同則是邊界

與方法四相比,大多數情況下,該方法更計算次數更少,在少部分情況下,方法是更好。但總體上方法5更好。

代碼如下:

package 微軟面試題數字次數;public class Test3 {public static void main(String[] args) {int[] arr={1,3,7,7,7,7,8,9,9,10};System.out.println("方法五測試:不存在key--"+GetNumberOfK(arr, 11));System.out.println("方法五測試:存在一個key--"+GetNumberOfK(arr, 3));System.out.println("方法五測試:存多個key--"+GetNumberOfK(arr, 9));}// (1)GetFirstK:找到數組中第一個k的下標。如果數組中不存在k,返回-1public static int GetFirstK(int[] data, int k, int start, int end) {if (start > end) {return -1;}int middIndex = (start + end) / 2;int middData = data[middIndex];if (middData == k) {if ((middIndex > 0 && data[middIndex - 1] != k) || middIndex == 0) {return middIndex;} else {end = middIndex - 1;}} else if (middData > k) {end = middIndex - 1;} else {start = middIndex + 1;}return GetFirstK(data, k, start, end);}// (2)GetLastK:找到數組中最后一個k的下標。如果數組中不存在k,返回-1public static int GetLastK(int[] data, int k, int start, int end) {if (start > end) {return -1;}int middIndex = (start + end) / 2;int middData = data[middIndex];if (middData == k) {if ((middIndex < data.length - 1 && data[middIndex + 1] != k) || middIndex == end) {return middIndex;} else {start = middIndex + 1;}} else if (middData > k) {end = middIndex - 1;} else {start = middIndex + 1;}return GetLastK(data, k, start, end);}// (3)GetNumberOfK:找到數組中第一個和最后一個k的下標進行減法運算得到最終結果public static int GetNumberOfK(int[] data, int k) {int number = 0;if (data != null && data.length > 0) {int first = GetFirstK(data, k, 0, data.length - 1);int last = GetLastK(data, k, 0, data.length - 1);if (first > -1 && last > -1) {number = last - first + 1;}}return number;}}

測試結果:

總結

以上是生活随笔為你收集整理的算法--微软面试:指定数字在数组中出现的次数的全部內容,希望文章能夠幫你解決所遇到的問題。

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