求数组的最大值和次大值

求数组A[] 在区间 [lo, hi) 内的最大值和第二大值。
返回最大值的下标x1和第二大值的下标x2


迭代1:
(迭代1的代码有bug,若A[lo]为最大值,则结果x1,x2都为lo)

void max2(int A[], int lo, int hi, int &x1, int &x2)
{
for(x1=lo, int i=lo+1; i<hi; i++)
if( A[i] > A[x1])
x1=i;
for(x2=lo, int i=lo+1; i<x1; i++)
if( A[i] > A[x2])
x2=i;
for(int i=x1+1; i<hi; i++)
if( A[i] > A[x2])
x2=i;
}

迭代2:
(相对于迭代1不会改进最坏情况下的时间复杂度)

void swap(int &x, int &y)
{ int t=x; x=y; y=t;}

void max2(int A[], int lo, int hi, int &x1, int &x2)
{
	if(A[x1=lo] < A[x2=lo+1]) //把x1设为最大值下标,x2设为次大值下标
		swap(x1,x2);
		
	for(int i=lo+2; i<hi; i++)
		if(A[i]>A[x2])  //先与A[x2]比较
			if(A[x2=i]>A[x1]) //若比A[x2]大,再把令x2指向i,然后A[x2]与A[x1]比较
				swap(x1,x2); //若比A[x1]也大,则交换x1,x2, 保持x1为最大,x2为次大
}

递归:
(分治法)
(把数组分为左右两个数组,分别求左右两个数组的最大值和次大值,然后再从结果中求最大值和次大值)

void swap(int &x, int &y)
{
	int t = x; x = y; y = t;
}

void max2(int A[], int lo, int hi, int &x1, int &x2)
{
	if (lo + 2 == hi)//区间内只剩2个元素,为递归基之一
	{
		if (A[x1 = lo] < A[x2 = lo + 1])
			swap(x1, x2);
		return;
	}
	if (lo + 3 == hi)//区间只剩3个元素,为递归基之一
	{
		if (A[x1 = lo] < A[x2 = lo + 1])
			swap(x1, x2);
		if (A[lo + 2] > A[x2])
			if (A[x2 = lo + 2] > A[x1])
				swap(x1, x2);
		return;
	}

	//分而治之
	int mi = (lo + hi) / 2;
	int x1l, x2l, x1r, x2r;
	max2(A, lo, mi, x1l, x2l);
	max2(A, mi, hi, x1r, x2r);
	if (A[x1l]>A[x1r])
	{
		x1 = x1l;
		x2 = A[x1r]>A[x2l] ? x1r : x2l;
	}
	else
	{
		x1 = x1r;
		x2 = A[x2r]>A[x1l] ? x2r : x1l;
	}
}

测试代码:

#include <stdio.h>
void max2(int A[], int lo, int hi, int &x1, int &x2);

int main()
{
	int arr[100];
	int n;
	while (scanf("%d", &n) == 1)
	{
		for (int i = 0; i < n; i++)
			scanf("%d", arr + i);

		printf("\n数组是:\n");
		for (int i = 0; i < n; i++)
			printf("%d ", arr[i]);
		int x1, x2;
		max2(arr, 0, n, x1, x2);
		printf("\n最大值:%d  次大值:%d\n", arr[x1], arr[x2]);
	}
	return 0;
}

ps: mi为什么可以这样算 mi = (lo+hi)/2
(虽然这个问题很简单,但是我当初纠结了好久,所以还是把它记下来了。)
最直观的算法mi=lo+(hi-lo)/2
化简
mi=lo+(hi-lo)/2
=lo + hi/2 - lo/2
=(2*lo)/2 + hi/2 - lo/2
=(2*lo +hi - lo) /2
=(lo + hi) /2
也可以借助下面的图片直观理解
在这里插入图片描述

发布了111 篇原创文章 · 获赞 13 · 访问量 3082

猜你喜欢

转载自blog.csdn.net/wx_assa/article/details/103994384