Introduction to Algorithms (算法导论) 学习笔记 -- Chapter 9

Chapter 9 Medians and Order Statistics (中位数和顺序统计)


n个元素中查找最小或最大元素,需要进行n-1次比对。


同时查找最小和最大的元素,最坏情况下需要进行⌈3n/2 - 2⌉次比较(⌈⌉为上取整)

证明:

对于n为奇数,初始设置min和max均为第一个元素,剩下n-1个元素为偶数,

对于n为偶数,比对前两个元素,设置较小的为min,较大的为max,剩下n-2个元素为偶数。


两两比对剩余的元素,较大者与max比对,较小者与min比对,并设置新的max和min。可见每对元素需要进行三次比较。因此:

对于奇数,共需比对的次数等于3(n-1)/2 = ⌊3n/2⌋ = ⌈3n/2⌉ - 1 < ⌈3n/2⌉ - 2

对于偶数,共需比对的次数等于1 + 3(n-2)/2 = 3n/2 - 2 = ⌈3n/2⌉ - 2


因此对于任何整数n,同时查找最小最大元素最坏情况下需要进行⌈3n/2 - 2⌉次比较。

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

void max_min(const int *arr, size_t n, int *pmax, int *pmin)
{
	int i;

	if ( 0 == n%2 ) /* even */
	{
		if ( arr[0] > arr[1] )
		{
			*pmax = arr[0];
			*pmin = arr[1];
		}
		else
		{
			*pmax = arr[1];
			*pmin = arr[0];
		}

		i = 2;
	}
	else
	{
		*pmax = *pmin = arr[0];
		i = 1;
	}

	while ( i < n )
	{
		if ( arr[i] > arr[i+1] )
		{
			if ( arr[i] > *pmax ) *pmax = arr[i];
			if ( arr[i+1] < *pmin ) *pmin = arr[i+1];
		}
		else
		{
			if ( arr[i+1] > *pmax ) *pmax = arr[i+1];
			if ( arr[i] < *pmin ) *pmin = arr[i];
		}

		i += 2;
	}
}

void do_min_max(size_t n)
{
	if ( n > 0 )
	{
		int i, min, max;
		int *arr = (int*)malloc(n*sizeof(int));
		if (!arr)
		{
			fprintf(stderr, "malloc buffer failed, n = %u\n", n);
			return;
		}

		srandom( (unsigned int)time(NULL) );
		printf("n=%u, arr={ ", n);
		for ( i = 0; i < n-1; ++i )
		{
			arr[i] = random() % (n*100);
			printf("%03d, ", arr[i]);
		}
		arr[i] = random() % (n*100);
		printf("%03d }", arr[i]);

		max_min(arr, n, &max, &min);
		printf(", min=%03d, max=%03d\n", min, max);

		free(arr);
	}
}

int main(int argc, char *argv[])
{
	if ( argc == 1 )
	{
		do_min_max(10);
	}
	else
	{
		int i;
		for ( i = 1; i < argc; ++i )
		{
			size_t n = (size_t)atoi(argv[i]);

			if ( n == 0 || n > 100 )
			{
				fprintf(stderr, "n = %u overflow, valid n is (0,100]\n", n);
				continue;
			}

			do_min_max(n);
		}
	}

	return 0;
}

/* eof */

# compile
~$ gcc -Wall -o max_min max_min.c
~$ ./max_min
~$ ./max_min 8 6 5

Exercises 9.1-1

Show that the second smallest of n elements can be found with n + ⌈lg n⌉ - 2 comparisons in the worst case. (Hint: Also find the smallest element.)

证明在n个元素中查找第二小的元素在最坏情况下需要n+⌈lg n⌉ - 2次比较。

      题外话:如果仅仅需要2n-3次比较,实现将非常简单:第一次获取最小的,并排除在外,需要n-1次比对。然后从n-1个元素中获取最小的即可,此时需要n-2次比对。因此需要2n-3次比较。


证明:

两两比对n个元素,对于较小元素,继续进行两两比对,如果某元素只剩余一个,则直接进入下一轮参加比对。因此,第一轮比对次数为⌊n/2⌋,第二轮比对次数为⌊ ⌊n/2⌋/2 ⌋,以此类推。该过程可以获得一个有n个叶子节点、n-1个内节点的二叉树。每个内节点对应一次比较,因此共有n-1次比较。例如:

1     8     7     4      6     3     5     9      2                         (第一次)
---------------------------------------------------
   1           4            3           5         2                         (第二次)
   ------------------------------------------------
         1                        3               2                         (第三次)
         ------------------------------------------
                      1                           2                         (第四次)
                      -----------------------------
                                     1
从根一直回朔到最小值所在叶子节点的路径上,令第二小的元素为第二层不等于最小值的节点,然后每层比较一次一直到叶子可得第二小的值。共需⌈lgn⌉ - 1次比较,故共需比较次数为n + ⌈lg n⌉ - 2次。


Exercises 9.1-2: ⋆

Show that ⌈3n/2⌉ - 2 comparisons are necessary in the worst case to find both the maximum and minimum of n numbers. (Hint: Consider how many numbers are potentially either the maximum or minimum, and investigate how a comparison affects these counts.)

证明同时查找最大最小值最坏情况下需要⌈3n/2⌉ - 2次比较(提示:考虑有多少个可能的最大最小值,考虑一次比对对这些值的影响)

参考本文最前面部分,已做证明。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值