码迷,mamicode.com
首页 > 其他好文 > 详细

LeetCode 之 Search for a Range(查找)

时间:2015-07-28 16:01:45      阅读:117      评论:0      收藏:0      [点我收藏+]

标签:leetcode   search for a range   prev   折半查找   二分查找   

【问题描述】

Given a sorted array of integers, find the starting and ending position of a given target value.

Your algorithm‘s runtime complexity must be in the order of O(log n).

If the target is not found in the array, return [-1, -1].

For example,
Given [5, 7, 7, 8, 8, 10] and target value 8,
return [3, 4].

1.【基础知识】

1)熟练掌握二分查找思想与源码

详见:数据结构基础 查找 之 二分查找

详址:http://blog.csdn.net/u013630349/article/details/47101881

2.【屌丝代码】

实现失败!

未实现原因:

1)不能处理好 mid、high、low 三者之间的关系;

2)不能处理好 边际条件 在 单变量、边界变量 查找的时候。

解决思路:

1)mid 递增和递减步骤;

2)mid 在采用非递归算法的时候,high作为上界值为size(),采用递归算法的时候值为size()-1;

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) 
	{
        int i;
		vector<int> myvec;
		if (nums.empty())
		{
			myvec.push_back(-1);
			myvec.push_back(-1);
			return myvec;
		}
		int low(0),high(nums.size()-1);
		if (nums[low]>target||nums[high]<target)
		{
			myvec.push_back(-1);
			myvec.push_back(-1);
			return myvec;
		}
		int mid = low+high/2,ind;
		while(high>=low)
		{
			if(target == nums[high])
			{	
				ind = high;
				break;
			}
			if(target > nums[mid])
			{
				low = mid;
				mid = (low+high)/2;
			}
			if(target == nums[high])
			{
				high = mid;
				mid = (low+high)/2;
			}
			if(target == nums[mid])
			{
				ind = mid;
				break;
			}
		}		
    	int max(ind),min(ind);
		for(i = ind;i<nums.size()&&nums[i] == nums[ind];i++)
		{
			max = i;
		}
		for(i = ind;i>0&&nums[i]==nums[ind];i--)
		{
			min = i;
		}
		for(i=min;i<=max;i++)
		{
			myvec.push_back(i);
		}
		for(i=0;i<myvec.size();i++)
		{
			cout<<myvec[i]<<endl;
		}
		return myvec;
	}
};

3.【源码AC】

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        const int l = distance(nums.begin(), lower_bound(nums.begin(), nums.end(), target));
        const int u = distance(nums.begin(), prev(upper_bound(nums.begin(), nums.end(), target)));
        if (nums[l] != target) // not found
        	return vector<int> { -1, -1 };
        else
        	return vector<int> { l, u };
    }
};

lower_bound 算法返回一个非递减序列[first, last)中的第一个大于等于 val 的位置。 

upper_bound 算法返回一个非递减序列[first, last)中的第一个大于 val 的位置。

distance算法返回两个输入参数的相对物理地址;

关于 prev 方法

If it is a random-access iterator, the function uses just once operator+ or operator-. Otherwise, the function uses repeatedly the increase or decrease operator (operator++ or operator--) on the copied iterator until n elements have been advanced.

【译】

如果是随机访问迭代器,就只执行一次运算符操作,否则,执行n次持续的递减或递增操作。

Random-access iterators are iterators that can be used to access elements at an arbitrary offset position relative to the element they point to, offering the same functionality as pointers.

【译】

随机访问迭代器是一种可以访问距离迭代器所指元素任意偏移地址元素的迭代器,其功能类似于指针。

prev函数:返回迭代器的前n个位置的迭代器

template <class BidirectionalIterator>
  BidirectionalIterator prev (BidirectionalIterator it,
       typename iterator_traits<BidirectionalIterator>::difference_type n = 1);

例:

要返回上述vector的最后一个元素:

cout  << prev(A.end() )  << endl;

要返回上述vector的倒数第3个元素:

cout  << prev(A.end() , 3)  << endl;

#include <iostream>     // std::cout
#include <iterator>     // std::next
#include <list>         // std::list
#include <algorithm>    // std::for_each


int main () {
  std::list<int> mylist;
  for (int i=0; i<10; i++) mylist.push_back (i*10);

  std::cout << "The last element is " << *std::prev(mylist.end()) << '\n'; // 90

  return 0;
}

关于advance方法

#include <iostream>     // std::cout
#include <iterator>     // std::advance
#include <list>         // std::list

int main () {
  std::list<int> mylist;
  for (int i=0; i<10; i++) mylist.push_back (i*10);

  std::list<int>::iterator it = mylist.begin();
  std::advance (it,3);  
  std::cout << "The sixth element in mylist is: " << *it << '\n';// 30
  it = mylist.end();  
  std::advance (it,-3);
  std::cout << "The sixth element in mylist is: " << *it << '\n';// 70

  return 0;
}

迭代器常见函数:

详见:C++ 标准库值操作迭代器的常见函数

详址:http://blog.csdn.net/xuqingict/article/details/32730477

4.【复盘】

1)卡壳部分
a.二分查找不熟悉,知识点记忆模糊,尤其是在mid的处理上;

b.在常见情况处理完毕后,尽量将特殊情况归一到常规处理之中,保证处理的统一性,实在丢不进去也无可厚非,添添补补能用即可,结果导向是第一位的!

2)算法思想

a.找到第一个等于该变量的索引‘l‘,找到第一个大于该变量的索引‘h‘+1;

b.如果,第一个等于该变量的索引未找到,返回{-1,-1},如果第一个大于该变量的索引未找到,则‘h‘+1=nums.size();

c.输出{l,h}即可;

3)后记

详见:C++ STL 迭代器方法 之 advance与prev 方法 浅析

详址:http://blog.csdn.net/u013630349/article/details/47105319

版权声明:本文为博主原创文章,未经博主允许不得转载。

LeetCode 之 Search for a Range(查找)

标签:leetcode   search for a range   prev   折半查找   二分查找   

原文地址:http://blog.csdn.net/u013630349/article/details/47099915

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!