一个二分搜索的设计

r11222 2010-06-06 05:42:46
思路跟普通二分搜索一样,但有个特别要求

如 1 2 3 3 3 3 4 5 6

如果数组中有相同的元素

当我查找3 时

要返回元素值为3 的 最小下标。

例子查找3时 返回值应该为 2(3的最小下标)。

麻烦优美点,谢谢。。。
...全文
106 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaoqiao_82 2010-06-06
  • 打赏
  • 举报
回复
如果数组确实很大,而且重复的元素确实比较多,可以继续采用类似“折半”查找的办法找到最小下标。
下面是我试着写的代码。

/*
int minIdx = mid;
while ( minIdx>low && entry[minIdx-1]==value ) {
minIdx--;
}
*/
high = mid; // 现在的目标是查找最小下标
while ( low < high ) { // 重复循环直到low == high
mid = ( low + high ) / 2;
if ( entry[mid] == value ) { // 最小下标在mid之前(或mid)
high = mid;
} else { // 最小下标在mid之后
low = mid + 1;
}
}
int minIdx = low;
xiaoqiao_82 2010-06-06
  • 打赏
  • 举报
回复
下面是以前做过的Java的代码,算法是相通的。

// 对数组进行折半查找
// 对于成功的查找,返回该值在数组中的范围(即最小索引和最大索引)
// 对于不成功的查找,返回null
public Bound search( int value ) throws IllegalArgumentException {
int low = 0;
int high = size - 1;
int mid;
while ( low <= high ) {
mid = (low + high) / 2;
if ( entry[mid] < value ) {
low = mid + 1;
} else if ( entry[mid] > value ) {
high = mid - 1;
} else {
// 确认数组中含有该值,下一步是确认该值在数组中的分布范围
// 确认该值的最小索引
int minIdx = mid;
while ( minIdx>low && entry[minIdx-1]==value ) {
minIdx--;
}
// 确认该值的最大索引
int maxIdx = mid;
while ( maxIdx<high && entry[maxIdx+1]==value ) {
maxIdx++;
}
return new Bound( minIdx, maxIdx );
}
}
return null;
}

在数组中找到符合的元素后,先默认它所在位置是最小下标minIdx。从该元素位置依次向前“探索”,如果其值也符合要求,就minIdx--,继续探索;如果不符合要求,返回minIdx值。
东莞某某某 2010-06-06
  • 打赏
  • 举报
回复
在二分法基础上稍微改下不OK了吗?
因为先前有序,找到后前后遍历,如果有相等的,取得下标。
r11222 2010-06-06
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 lqbk2 的回复:]
贴一个stl里面的lower_bound
思路是一样的
楼主可以自行将其转化成c的形式

C/C++ code

/**
* @brief Finds the first position in which @a val could be inserted
* without changing the ordering.
* @param ……
[/Quote]


good!
谢谢!
r11222 2010-06-06
  • 打赏
  • 举报
回复
不行哦,,,数据很大,遍历就太慢了,数据本身就有序,但要求一定要找到最小的小标,也一定要是二分法。。。
z569362161 2010-06-06
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 huanmie_09 的回复:]
这个遍历查找不就行了么。找到元素后立即退出查找, 返回的就是元素的最小下标.
如果先前无序的话排下序就好了.
[/Quote] 只有引用的内容不允许回复!
lqbk2 2010-06-06
  • 打赏
  • 举报
回复
贴一个stl里面的lower_bound
思路是一样的
楼主可以自行将其转化成c的形式

/**
* @brief Finds the first position in which @a val could be inserted
* without changing the ordering.
* @param first An iterator.
* @param last Another iterator.
* @param val The search term.
* @return An iterator pointing to the first element "not less
* than" @a val, or end() if every element is less than
* @a val.
* @ingroup binary_search_algorithms
*/
template<typename _ForwardIterator, typename _Tp>
_ForwardIterator
lower_bound(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __val)
{
typedef typename iterator_traits<_ForwardIterator>::value_type
_ValueType;
typedef typename iterator_traits<_ForwardIterator>::difference_type
_DistanceType;

// concept requirements
__glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
__glibcxx_function_requires(_LessThanOpConcept<_ValueType, _Tp>)
__glibcxx_requires_partitioned_lower(__first, __last, __val);

_DistanceType __len = std::distance(__first, __last);
_DistanceType __half;
_ForwardIterator __middle;

while (__len > 0)
{
__half = __len >> 1;
__middle = __first;
std::advance(__middle, __half);
if (*__middle < __val)
{
__first = __middle;
++__first;
__len = __len - __half - 1;
}
else
__len = __half;
}
return __first;
}
huanmie_09 2010-06-06
  • 打赏
  • 举报
回复
这个遍历查找不就行了么。找到元素后立即退出查找, 返回的就是元素的最小下标.
如果先前无序的话排下序就好了.

69,336

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧