/*******************************************************************
Copyright(c) 2016, Tyrone Li
All rights reserved.
*******************************************************************/
// 作者:TyroneLi
//
/*
Q:
數字在排序數組中出現的次數:
統計一個數字在排序數組中出現的次數,例如輸入排序數組{1,2,3,3,3,4,5},由於
3在排序數組中出現3次,因此輸出4.
S:
1. 使用二分查找算法查找出該數字,那麼該數組分別向兩邊遍歷知道遇到不同數字爲止,
那麼改數字出現的次數就可以通過兩次遍歷的次數加和得到。
2. 借鑑二分查找算法,這裏只用找出第一個出現查找數字的位置以及最後一個查找位置,就
可以求出該數字出現的次數;查找第一個出現的數字時候,如果二分查找的中間數字比需要
查找的數字大,那麼需要查找的數字在前半部分,如果中間部分的數字比需要查找的數字小,
那麼需要在後半部分查找;如果剛好等於,對於查找第一次出現的數字,如果該數字前面的
數字不等於該數字,就爲所求,否則就是在前半部分繼續查找;對於最後一次出現的數字,
如果後面的數字不等於該數字,則爲所求,否則繼續在後部分查找。
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
int binarySearch(int*data, int start, int end, int k)
{
if(data == nullptr || start > end || start < 0)
return -1;
int mid = (start + end) / 2;
if(data[mid] == k)
return mid;
else if(data[mid] < k)
return binarySearch(data, mid+1, end, k);
else
return binarySearch(data, start, mid-1, k);
}
void test_binarySearch()
{
int data[] = {1,2,3,4,5,6,7,8,9,10};
int rst_idx = binarySearch(data, 0, 9, 3);
for(auto e:data)
std::cout << e << " ";
std::cout << std::endl;
std::cout << "idx = " << rst_idx << " data = " << data[rst_idx] << std::endl;
}
void test_binarySearch_2()
{
int data[] = {1};
int rst_idx = binarySearch(data, 0, 0, 1);
for(auto e:data)
std::cout << e << " ";
std::cout << std::endl;
std::cout << "idx = " << rst_idx << " data = " << data[rst_idx] << std::endl;
}
int countKNums_merge(int*data, int length, int k)
{
if(data == nullptr || length <= 0)
return -1;
int k_idx = binarySearch(data, 0, length-1, k);
if(k_idx < 0)
return 0;
int pre_k = 0;
int post_k = 0;
for(int i = k_idx; i >= 0; --i)
{
if(data[i] != k)
{
pre_k = i+1;
break;
}
}
for(int i = k_idx; i <= length; ++i)
{
if(data[i] != k)
{
post_k = i-1;
break;
}
}
// std::cout << "k_idx=" << k_idx << std::endl;
// std::cout << "pre_k=" << pre_k << " post_k=" << post_k << std::endl;
return (post_k - pre_k + 1);
}
int getFirstK(int*data, int length, int k, int start, int end)
{
if(data == nullptr || length <= 0 || start > end)
return -1;
int mid = (start + end) / 2;
int mid_data = data[mid];
if(mid_data < k)
{
start = mid + 1;
}else if(mid_data > k)
{
end = mid - 1;
}else{
if(mid == 0 || mid > 0 && data[mid-1] != k)
return mid;
else
end = mid - 1;
}
return getFirstK(data, length, k, start, end);
}
int getLastK(int*data, int length, int k, int start, int end)
{
if(data == nullptr || length <= 0 || start > end)
return -1;
int mid = (start + end) / 2;
int mid_data = data[mid];
if(mid_data < k)
{
start = mid + 1;
}else if(mid_data > k)
{
end = mid - 1;
}else{
if(mid == (length - 1) || mid < (length - 1) && data[mid+1] != k)
return mid;
else
start = mid + 1;
}
return getLastK(data, length, k, start, end);
}
int countKNums_FirstLast(int*data, int length, int k)
{
if(data == nullptr || length <= 0)
return -1;
int number = 0;
if(data != nullptr && length > 0)
{
int first_idx = getFirstK(data, length, k, 0, length-1);
int last_idx = getLastK(data, length, k, 0, length-1);
// std::cout << "first_idx=" << first_idx << " last_idx=" << last_idx << std::endl;
if(first_idx >= 0 && last_idx >= 0)
{
number = last_idx - first_idx;
}
}
return number;
}
void test_1()
{
std::cout << "Test 1" << std::endl;
int data[] = {1,2,3,3,3,3,4,5,6,7};
for(auto e:data)
std::cout << e << " ";
std::cout << std::endl;
int repeat_nums_1 = countKNums_merge(data, 10, 3);
int repeat_nums_2 = countKNums_FirstLast(data, 10, 3);
std::cout << " 3 repeat times : " << repeat_nums_1 << std::endl;
std::cout << " 3 repeat times : " << repeat_nums_2 << std::endl << std::endl;
}
void test_2()
{
std::cout << "Test 2" << std::endl;
int data[] = {1,2,3,3,3,3,4,5,6,7};
for(auto e:data)
std::cout << e << " ";
std::cout << std::endl;
int repeat_nums_1 = countKNums_merge(data, 10, 8);
int repeat_nums_2 = countKNums_FirstLast(data, 10, 8);
std::cout << " 8 repeat times : " << repeat_nums_1 << std::endl;
std::cout << " 8 repeat times : " << repeat_nums_2 << std::endl;
}
void test_3()
{
std::cout << "Test 3" << std::endl;
int data[] = {1,2,3,4,5,6,7,8,9,10};
for(auto e:data)
std::cout << e << " ";
std::cout << std::endl;
int repeat_nums_1 = countKNums_merge(data, 10, 3);
int repeat_nums_2 = countKNums_FirstLast(data, 10, 3);
std::cout << " 3 repeat times : " << repeat_nums_1 << std::endl;
std::cout << " 3 repeat times : " << repeat_nums_2 << std::endl;
}
void test_4()
{
std::cout << "Test 4" << std::endl;
int data[] = {1,2,3,3,3,3,4,5,6,7};
for(auto e:data)
std::cout << e << " ";
std::cout << std::endl;
int repeat_nums_1 = countKNums_merge(data, 10, 1);
int repeat_nums_2 = countKNums_FirstLast(data, 10, 1);
std::cout << " 1 repeat times : " << repeat_nums_1 << std::endl;
std::cout << " 1 repeat times : " << repeat_nums_2 << std::endl;
}
void test_5()
{
std::cout << "Test 5" << std::endl;
int data[] = {1,2,3,3,3,3,4,5,6,7};
for(auto e:data)
std::cout << e << " ";
std::cout << std::endl;
int repeat_nums_1 = countKNums_merge(data, 10, 7);
int repeat_nums_2 = countKNums_FirstLast(data, 10, 7);
std::cout << " 7 repeat times : " << repeat_nums_1 << std::endl;
std::cout << " 7 repeat times : " << repeat_nums_2 << std::endl;
}
void test_6()
{
std::cout << "Test 6" << std::endl;
int data[] = {1,1,3,3,3,3,4,5,6,7};
for(auto e:data)
std::cout << e << " ";
std::cout << std::endl;
int repeat_nums_1 = countKNums_merge(data, 10, 1);
int repeat_nums_2 = countKNums_FirstLast(data, 10, 1);
std::cout << " 1 repeat times : " << repeat_nums_1 << std::endl;
std::cout << " 1 repeat times : " << repeat_nums_2 << std::endl;
}
void test_7()
{
std::cout << "Test 7" << std::endl;
int data[] = {1,2,3,3,3,3,4,5,7,7};
for(auto e:data)
std::cout << e << " ";
std::cout << std::endl;
int repeat_nums_1 = countKNums_merge(data, 10, 7);
int repeat_nums_2 = countKNums_FirstLast(data, 10, 7);
std::cout << " 7 repeat times : " << repeat_nums_1 << std::endl;
std::cout << " 7 repeat times : " << repeat_nums_2 << std::endl;
}
void test_8()
{
std::cout << "Test 8" << std::endl;
int data[] = {1};
for(auto e:data)
std::cout << e << " ";
std::cout << std::endl;
int repeat_nums_1 = countKNums_merge(data, 10, 1);
int repeat_nums_2 = countKNums_FirstLast(data, 10, 1);
std::cout << " 1 repeat times : " << repeat_nums_1 << std::endl;
std::cout << " 1 repeat times : " << repeat_nums_2 << std::endl;
}
void test_9()
{
std::cout << "Test 9" << std::endl;
int*data = nullptr;
// for(auto e:data)
// std::cout << e << " ";
std::cout << std::endl;
int repeat_nums_1 = countKNums_merge(data, 10, 3);
int repeat_nums_2 = countKNums_FirstLast(data, 10, 3);
std::cout << " 3 repeat times : " << repeat_nums_1 << std::endl;
std::cout << " 3 repeat times : " << repeat_nums_2 << std::endl;
}
void test_countKNums()
{
test_1();
test_2();
test_3();
test_4();
test_5();
test_6();
test_7();
test_8();
test_9();
}
int main(int argc, char**argv)
{
// test_binarySearch();
// test_binarySearch_2();
test_countKNums();
// std::system("pause");
return 0;
}
劍指offer-統計排序數組中某數字出現的次數
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.