統計一個數字在排序數組中出現的次數。例如:排序數組{1,2,3,3,3,3,4,5},和數字3,由於3在這個數字中出現了4次,因此輸出4。
解法1:順序掃描,統計該數字出現的次數,時間複雜度爲O(n)。
解法2:利用二分查找,找到一個數字,由於該數字可能出現多次,有可能該數字前後都有可能是所找的數字,因此向兩邊順序掃描,找出第一個該數字和最後一個該數字。由於數字在長度爲n的數組中有可能出現O(n)次,所以時間複雜度爲O(n)。
這兩種解法在本質上是一樣的。
解法3:更好的利用二分查找,找到第一個該數字的位置,找到最後一個該數字的位置。
二分查找總是用中間的數字與所找的數字K進行比較,如果中間的數字比K小,向後找;如果中間的數字比K大,向前找;如果相等,我們來進行處理。
假設我們要找第一個K,如果中間數字是K,前一個數字不是K,則中間數字就是我們要找的第一次出現的K;如果中間數字是K,前一個數字也是K,說明第一次出現的K在前面,我們繼續向前找。
同樣的方法我們可以找到最後一個K。判斷中間數字是不是最後一個K,可以看中間數字的後一位是不是K,不是K,則中間數字就是最後一個K;後一個數字是K,則繼續向後找。
class Solution {
public:
int GetFirstK(vector<int>data,int length,int k,int start,int end)
{
if(start > end)
return -1;
int middleindex = (start + end)/2 ;
int middledata = data[middleindex];
if(middledata == k)
{
if((middleindex > 0 && data[middleindex -1] != k) || middleindex == 0)
return middleindex;
else
end = middleindex-1;
}
else if(middledata > k)
end = middleindex-1;
else
start = middleindex +1;
return GetFirstK(data,length,k,start,end);
}
int GetLastK(vector<int>data,int length,int k,int start,int end)
{
if(start > end)
return -1;
int middleindex = (start + end)/2 ;
int middledata = data[middleindex];
if(middledata == k)
{
if((middleindex < length-1 && data[middleindex +1] != k) || middleindex == length-1)
return middleindex;
else
start = middleindex+1;
}
else if(middledata > k)
end = middleindex-1;
else
start = middleindex +1;
return GetLastK(data,length,k,start,end);
}
int GetNumberOfK(vector<int> data ,int k)
{
int number = 0;
int length = data.size();
if(length >0)
{
int first = GetFirstK(data,length,k,0,length-1);
int last = GetLastK(data,length,k,0,length-1);
if(first >-1 && last >-1)
number = last - first +1;
}
return number;
}
};
GetFirstK,GetLastK,都是利用二分查找在數組中查找一個數字,時間複雜度是O(logn),因此總的時間複雜度也是O(logn)。