您的位置:首页 > 其它

leetcode-81-Search in Rotated Sorted Array II 查找

2016-11-06 23:14 465 查看

问题

题目:[leetcode-81]

思路

[leetcode-33]相比,主要是重复元素的问题。举两个例子:

[3,5,5,5,1]和[5,1,1,1,3],对于这种情况,算法的其余部分基本不变。

首先,是pivot的查找问题。

我做如下定义,如果一个序列存在一个升序对和一个降序对,那么我认为这个序列而存在一个逆序。那么现在的问题就转换为判断一个序列中是否存在一个逆序对。当前问题与之前问题的区别是,之前的问题逆序对是连续的。但是现在的逆序对是不连续的。

鉴于此,我的办法是分别设置一对升序和降序的标志。逆序的存在用这对标志进行判断。

其次,pivot的返回值对于这两种情形也稍有不同。

[3,5,5,5,1]的pivot=4,[5,1,1,1,3]的pivot = 2。对于后者pivot是第一个升序出现的地方。前者的pivot是第一个降序出现的地方。

再者,在执行search函数的时候,对于不存在逆序的序列进行查找的时候。需要判断第一个元素和最后一个元素来判断到底是升序,还是降序。

代码(c实现)

// c version
int find_pivot( int* arr, int n )
{
if( NULL == arr || n <= 0 )
return -1;

bool asd = false; // 升序标志
bool des = false; // 降序标志
int first = 0;
for( int i = 1; i < n - 1; ++i ) // arr[0] arr[n-1]一定不是pivot
{
if( arr[i - 1] < arr[i] )
asd = true;
if( arr[i - 1] > arr[i] )
{   des = true; first = i;   }
if( arr[i] > arr[i + 1] )
des = true;
if( arr[i] < arr[i+1] )
asd = true;

if( asd && des )
{
if( arr[i] < arr[i + 1] )
return first;
else if( arr[i] > arr[i+1] )
return i + 1;
}
}
return 0;
}

bool bi_search1( int* arr, int n, int key )
{
if( NULL == arr || n <= 0 )
return false;
else
{
int low = 0, high = n-1;
int mid = 0;
while( low <= high )
{
int mid = (low + high)/2;
if( key == arr[mid] )
return true;
else if( key < arr[mid] )
high = mid - 1;
else
low = mid + 1;
}
return false;
}
}
int bi_search2( int* arr, int n, int key )
{
if( NULL == arr || n <= 0 )
return false;
else
{
int low = 0, high = n-1;
int mid = 0;
while( low <= high )
{
int mid = (low + high)/2;
if( key == arr[mid] )
return true;
else if( key < arr[mid] )
low = mid + 1;
else
high = mid - 1;
}
return false;
}
}

bool search(int* nums, int numsSize, int target) {

int pivot = find_pivot( nums, numsSize );
printf( "pivot = %d\n", pivot );
if( -1 == pivot )
return false;
else if( !pivot )
{
if( numsSize > 1 )
{
if( nums[0] < nums[numsSize-1] )
return bi_search1( nums, numsSize, target ) ; // 升序
else
return bi_search2( nums, numsSize, target );  // 降序
}
else
return bi_search1( nums, numsSize, target ) ; // 升序
}
else
{
if( target >= nums[0] ) // 大序列查找
{
return bi_search1( nums, pivot + 1, target );
}
else // 小序列查找
{
return bi_search1( nums + pivot , numsSize - pivot , target );

}
}
}


思路1

我在用c++重写的时候,由于隔了一天。没有沿用之前的思路,就是按照思路去写的。其实大体思路差不多。

寻找pivot

判断在哪个序列中进行查找

在想应的序列查找即可

更新,find_pivot代码我做了一点更新,当然基本思路和c的方法一样。还是寻找代码中的逆序。需要设置两个标签。

还有,我注意到一个之前没有很好认识的性质。其实这个rotated array在pivot的前后,都是升序,只不过一个是大序列,一个是小序列。

由于返回的都是后面序列的第一个元素,所以我做了一点技巧。还是说例子。

[3,5,1],[5,1,3],前者pivot = 2,后者pivot = 1。特点是,如果先降序后升序,那么pivot = i.如果是先降序后升序,那么pivot需要在之前保存。

int find_pivot( const std::vector<int>& nums )
{
int sz = nums.size();
if( !sz )
return -1;

bool asc = false;
bool des = false;
int first = 0;

for( int i = 1; i < sz ; ++i )
{
if( nums[i-1] < nums[i] )
asc = true;
else if( nums[i-1] > nums[i] )
{
if( !asc )
first = i;
des = true;
}

if( asc && des )
{
if( first )
return first;
else
return i;
}

}

return 0; // 不存在逆序

}


剩下的思路一样。

代码(c++实现)

class Solution {
public:
bool search( std::vector<int>& nums, int target) {
int sz = nums.size();
if(!sz)
return false;

int pivot = find_pivot( nums );
//std::cout << "pivot = " << pivot << std::endl;
if( -1 == pivot )
return false;
else if( !pivot )
{
if( sz > 1 )
{
if( nums[0] > nums[sz-1] )
return bi_search2( nums, target );
else
return bi_search1( nums, target );
}
else
return bi_search1( nums, target );
}
else
{
if( target >= nums[0] )
{
return bi_search1( std::vector<int>( nums.begin(), nums.begin() + pivot ), target );
}
else
{
return bi_search1( std::vector<int>( nums.begin() + pivot, nums.end() ), target );
}
}

return true;
}
private:

int find_pivot( const std::vector<int>& nums )
{
int sz = nums.size();
if( !sz )
return -1;

bool asc = false;
bool des = false;
int first = 0;

for( int i = 1; i < sz; ++i )
{
if( nums[i-1] < nums[i] )
asc = true;
else if( nums[i-1] > nums[i] )
{
if( !asc )
first = i;
des = true;
}

if( asc && des )
{
if( first )
return first;
else
return i;
}

}

return 0; // 不存在逆序

}

bool bi_search1( const std::vector<int>& nums, int target )
{
int sz = nums.size();
if( !sz )
return false;
int low = 0;
int high = sz-1;
while( low <= high )
{
int mid = ( low + high )/2;
if( nums[mid] == target )
return true;
else if( target < nums[mid] )
high = mid - 1;
else
low = mid + 1;
}
return false;
}
bool bi_search2( const std::vector<int>& nums, int target )
{
int sz = nums.size();
if( !sz )
return false;
int low = 0;
int high = sz-1;
while( low <= high )
{
int mid = ( low + high )/2;
if( nums[mid] == target )
return true;
else if( target < nums[mid] )
low = mid + 1;
else
high = mid - 1;
}
return false;
}
};


再刷

参考:[leetcode-81]

出现重复元素的问题在于,[3,1,1]以及[1,1,3,1],此时3可以在左或者右,那么基本思路还是要比,直到存在a[mid]和a[right]的大小值不同时为止。

class Solution {
public:
bool search(vector<int>& nums, int target) {
int sz = nums.size();
if(!sz) return false;

int low = 0, high = sz-1;
while(low <= high) {
int mid = (low+high)/2;
if( nums[mid] == target ) return true;

if( nums[mid] < nums[high] ) {
if( nums[mid] < target && target <= nums[high] ) low = mid+1;
else high = mid-1;
}
else if( nums[mid] > nums[high] ) {
if( nums[low] <= target && target < nums[mid] ) high = mid-1;
else low = mid + 1;
}
else high--;
}
return false;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: