求最大值最小值的方法 时间复杂度O(n)

本文介绍了一个使用C++实现的随机数生成器,该生成器限制了重复的随机数生成,并展示了如何在序列中找到最大值和最小值。通过模板类`Urand`,可以为指定范围生成不重复的随机数,同时,文章还提供了处理数组元素以确定最大和最小值的逻辑。
#include<iostream>    
#include <iostream>
#include <bitset>
#include <ctime>
using namespace std;

template <size_t UpperBound> class Urand{      //生成随机数
  bitset<UpperBound> used;
public:
	Urand(){ srand(time(0)); }
	double operator() ();
};

template<size_t UpperBound>
inline double Urand<UpperBound>::operator()()
{
	if(used.count() == UpperBound)
		used.reset();
	size_t newval;
	while(used[newval = rand() % UpperBound])
		;
	used[newval] = true;
	return newval*0.1;
}

int main(int argc, char* argv[])
{
	Urand<10> u;
	double darr[10];
	double first = 0.0;
	double second = 0.0;
	double min = 0.0;
	double max = 0.0;
	for ( int i = 0; i < 10; ++i)
	{
		darr[i] = u();
	}
    
	int num = sizeof(darr)/sizeof(darr[0]);
	bool flag = false;

	if( num%2==0 )
    {
        flag = true;
    }
	else
	{
        flag = false;
	}
    
	if(flag)
	{  
	   int i= 0;
	   first = darr[0];
	   second = darr[1];
	   if(first<second)
	   {
          min = first;
		  max = second;
	   }
	   else
	   {
          min = second;
		  max = first;
	   }
	}
	else
	{
		min = darr[0];
		max = darr[0];
	}
	
	   for( flag? i=2 : i=1; i<num; i+=2 )
	   {
            if( darr[i]<darr[i+1] )
			{
			    if( min>darr[i] ) 
				{
                    min = darr[i];
				}
				if( max<darr[i+1] )
				{
                    max = darr[i+1];
				}
			}
			else
			{
                if( min>darr[i+1] )
				{
                    min = darr[i+1];
				}
				if( max<darr[i])
				{
					max = darr[i];
				}

			}
	   }
	
    cout<<"Max :"<<max<<endl;
	cout<<"Min :"<<min<<endl;
	return 0;
}


<think>好的,我现在需要帮助用户分析C语言中使用二分法查找最大最小值时间复杂度。首先,我得先理解用户的问题。用户提到了二分法,通常二分法用于有序数组中的查找,但有时候也可以用于某些特定条件下的无序数组,比如寻找局部最小值。不过,查找最大最小值通常需要遍历整个数组,时间复杂度是线性的,即O(n)。但用户可能指的是某种特定的情况,比如部分有序或者有其他约束条件的情况。 首先,我需要回顾一下用户提供的引用内容。引用[1]提到在无序数组中用二分法找局部最小值的位置,这可能与用户的问题相关。但用户的问题是关于最大最小值,而局部最小值可能只需要部分比较。不过,通常情况下,找全局的最大值最小值无法用二分法,因为需要遍历所有元素才能确定。例如,在一个无序数组中,最大值可能在任意位置,必须检查每个元素才能确定,所以时间复杂度是O(n)。 但用户可能误解了某些应用场景。例如,在旋转排序数组中寻找最小值,如引用[4]中的LeetCode题目,这种情况下数组是部分有序的,可以用二分法在O(log n)时间内找到最小值。这种情况下,虽然数组不是完全有序,但根据旋转后的特性,可以利用二分法来缩小搜索范围。这可能就是用户提到的二分法查找最小值的例子。 所以,用户的问题可能混淆了两种情况:一种是在完全无序的数组中找最大最小值,这必须用线性扫描;另一种是在部分有序的数组(如旋转排序数组)中使用二分法,这时候时间复杂度可以降低到O(log n)。需要明确用户的具体情况。 接下来,我需要分析这两种情况的时间复杂度: 1. **无序数组中的最大/最小值查找**:必须遍历所有元素,时间复杂度是O(n),无法用二分法优化,因为无法确定哪一部分包含极值。例如,即使中间元素比左边的大,也不能排除最大值在右边或左边的情况。因此,必须逐个检查。 2. **部分有序数组中的极值查找**:例如旋转排序数组,这种情况下可以利用数组的部分有序性。例如,旋转后的数组分为两个有序部分,通过比较中间元素与端点元素,可以确定最小值在哪一半,从而将搜索范围减半,时间复杂度是O(log n)。这种情况下,二分法是有效的。 用户提供的引用中,引用[2]提到时间复杂度为O(log(m+n)),这可能是在合并两个有序数组时的情况,而引用[4]中的问题确实使用二分法在旋转数组中找最小值时间复杂度是O(log n)。这说明在某些特定结构的数据中,二分法可以用于极值查找,但并非所有情况。 因此,回答用户的问题时,需要区分两种情况: - 如果数组是完全无序的,没有特定结构,那么查找最大最小值时间复杂度是O(n),无法用二分法优化。 - 如果数组具有某种结构(如旋转后的有序数组),则可以用二分法,时间复杂度是O(log n)。 用户的问题提到“二分法查找最大最小值”,可能需要进一步澄清应用场景。例如,在旋转数组中找最小值属于特殊情况,此时时间复杂度为O(log n),而一般情况下是O(n)。 总结来说,回答需要明确不同情况下的时间复杂度,并举例说明适用的场景,如旋转数组的情况,同时指出一般情况下二分法不适用于无序数组的极值查找。</think>### 逐步解释 1. **二分法的基本应用场景** 二分法通常要数据具备**有序性**或**局部有序性**。对于完全无序的数组,二分法无法直接用于查找最大值最小值,因为无法通过中间值判断极值所在的区域。此时必须遍历所有元素,时间复杂度为$O(n)$[^4]。 2. **特殊情况:部分有序数组的极值查找** 若数组具有某种结构特征(例如**旋转后的有序数组**),则可以通过二分法优化。例如,在旋转排序数组中寻找最小值时,时间复杂度可降至$O(\log n)$。 **算法逻辑**: - 比较中间元素与右边界元素。 - 若中间元素小于右边界,说明最小值在左半部分。 - 否则,最小值在右半部分。 - 不断缩小范围直到找到最小值。 3. **时间复杂度分析** - **一般无序数组**:必须遍历所有元素,时间复杂度为$O(n)$。 - **部分有序数组**(如旋转排序数组):二分法每次将范围缩小一半,时间复杂度为$O(\log n)$[^2]。 --- ### 示例代码(旋转排序数组的最小值查找) ```c int findMin(int* nums, int numsSize) { int left = 0, right = numsSize - 1; while (left < right) { int mid = left + (right - left) / 2; if (nums[mid] < nums[right]) { right = mid; } else { left = mid + 1; } } return nums[left]; } ``` --- ### 总结表格 | 场景 | 时间复杂度 | 适用条件 | |---------------------|------------|------------------------| | 完全无序数组 | $O(n)$ | 无任何结构特征 | | 旋转排序数组 | $O(\log n)$| 数组部分有序 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值