#資料結構與演算法學習筆記#劍指Offer35:數字在排序陣列中出現的次數 + 測試用例(Java、C/C++)
阿新 • • 發佈:2018-12-17
2018.10.24
今天是程式設計師節,但是程式設計師有啥節好過的,還是好好幹活吧~
這道題也是一道效率題,根據實際情況的不同有兩個比較好用的方法:
方法一:平均複雜度o(n)。二分找到某一個K的位置,從該位置起向前向後分別計數後求和。對K數量較少時好用。
方法二:平均複雜度o(logn)。找到K起始和結束位置,做差計算中間K的個數。對K數量較多時好用。
雖然平均複雜度差別很大,但是在實際情況中卻都有應用。
題目描述
統計一個數字在排序陣列中出現的次數。
Java實現示例:
/** * * @author ChopinXBP * 統計一個數字在排序陣列中出現的次數。 * */ public class GetNumberOfK_36 { public static void main(String[] args) { // TODO Auto-generated method stub int [] array = {3, 3, 3, 3, 4, 5}; System.out.println(GetNumberOfK1(array, 3)); System.out.println(GetNumberOfK2(array, 6)); } //方法一:平均複雜度o(n)。二分找到某一個K的位置,從該位置起向前向後分別計數後求和。對K數量較少時好用。 public static int GetNumberOfK1(int [] array , int k) { if(array == null || array.length == 0) return 0; int location = array.length >> 1; int begin = 0; int end = array.length - 1; while(begin != end){ if(array[location] == k) break; else if(array[location] < k) begin = location + 1; else if(array[location] > k) end = location - 1; location = (begin + end) >> 1; } int count = 0; int p = location - 1; while(p >= 0 && array[p--] == k) count++; while(location < array.length && array[location++] == k)count++; return count; } //方法二:複雜度o(logn),找到某一個K起始和結束位置,計算中間K的個數,對K數量較多時好用 public static int GetNumberOfK2(int [] array , int k) { if(array == null || array.length == 0) return 0; //獲得K起始位置 int location1 = array.length >> 1; int begin = 0; int end = array.length - 1; while(begin <= end){ if(array[location1] < k) begin = location1 + 1; else end = location1 - 1; location1 = (begin + end) >> 1; } location1++; //原演算法返回的是第一個K的前一個位置 //獲得K結束位置 int location2 = array.length >> 1; begin = 0; end = array.length - 1; while(begin <= end){ if(array[location2] <= k) begin = location2 + 1; else end = location2 - 1; location2 = (begin + end) >> 1; } return location2 - location1 + 1; } }
C++實現示例:
class Solution { /*二分查詢 找到第一個K 和 最後一個K 二者位置相減*/ public: int GetNumberOfK(vector<int> data ,int k) { if(data.empty()) return 0; int number = 0; int first = GetFirstIndex(data,k,0,data.size()-1); int last = GetLastIndex(data,k,0,data.size()-1); if(first>-1 && last>-1) number = last - first +1; return number; } int GetFirstIndex(vector<int> &data,int k,int start,int end){ if(start > end) return -1; int mid = start+(end-start)/2; if(data[mid] == k){ if((mid == start) || (data[mid-1] != k)) return mid; else end = mid-1; } else{ if(data[mid] > k) end = mid - 1; else start = mid + 1; } return GetFirstIndex(data,k,start,end); } int GetLastIndex(vector<int> &data,int k,int start,int end){ if(start > end) return -1; int mid = start+(end-start)/2; if(data[mid]==k){ if((mid == end) || (data[mid+1] != k)) return mid; else start = mid +1; } else{ if(data[mid]>k) end = mid-1; else start = mid+1; } return GetLastIndex(data,k,start,end); } };
測試程式碼:
// ====================測試程式碼==================== void Test(char* testName, int data[], int length, int k, int expected) { if(testName != NULL) printf("%s begins: ", testName); int result = GetNumberOfK(data, length, k); if(result == expected) printf("Passed.\n"); else printf("Failed.\n"); } // 查詢的數字出現在陣列的中間 void Test1() { int data[] = {1, 2, 3, 3, 3, 3, 4, 5}; Test("Test1", data, sizeof(data) / sizeof(int), 3, 4); } // 查詢的陣列出現在陣列的開頭 void Test2() { int data[] = {3, 3, 3, 3, 4, 5}; Test("Test2", data, sizeof(data) / sizeof(int), 3, 4); } // 查詢的陣列出現在陣列的結尾 void Test3() { int data[] = {1, 2, 3, 3, 3, 3}; Test("Test3", data, sizeof(data) / sizeof(int), 3, 4); } // 查詢的數字不存在 void Test4() { int data[] = {1, 3, 3, 3, 3, 4, 5}; Test("Test4", data, sizeof(data) / sizeof(int), 2, 0); } // 查詢的數字比第一個數字還小,不存在 void Test5() { int data[] = {1, 3, 3, 3, 3, 4, 5}; Test("Test5", data, sizeof(data) / sizeof(int), 0, 0); } // 查詢的數字比最後一個數字還大,不存在 void Test6() { int data[] = {1, 3, 3, 3, 3, 4, 5}; Test("Test6", data, sizeof(data) / sizeof(int), 6, 0); } // 陣列中的數字從頭到尾都是查詢的數字 void Test7() { int data[] = {3, 3, 3, 3}; Test("Test7", data, sizeof(data) / sizeof(int), 3, 4); } // 陣列中的數字從頭到尾只有一個重複的數字,不是查詢的數字 void Test8() { int data[] = {3, 3, 3, 3}; Test("Test8", data, sizeof(data) / sizeof(int), 4, 0); } // 陣列中只有一個數字,是查詢的數字 void Test9() { int data[] = {3}; Test("Test9", data, sizeof(data) / sizeof(int), 3, 1); } // 陣列中只有一個數字,不是查詢的數字 void Test10() { int data[] = {3}; Test("Test10", data, sizeof(data) / sizeof(int), 4, 0); } // 魯棒性測試,陣列空指標 void Test11() { Test("Test11", NULL, 0, 0, 0); } int _tmain(int argc, _TCHAR* argv[]) { Test1(); Test2(); Test3(); Test4(); Test5(); Test6(); Test7(); Test8(); Test9(); Test10(); Test11(); return 0; }
#Coding一小時,Copying一秒鐘。留個言點個讚唄,謝謝你#