/*******************************************************************
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-统计排序数组中某数字出现的次数
最新推荐文章于 2021-05-10 11:56:55 发布