【华为OJ】【024-合唱队】

题目描述

计算最少出列多少位同学,使得剩下的同学排成合唱队形

说明:

N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。 
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK,   则他们的身高满足存在i(1<=i<=K)使得T1Ti+1>......>TK。 
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。 

输入描述:

整数N

输出描述:

最少需要几位同学出列

示例1

输入

8
186 186 150 200 160 130 197 200

输出

4

本题考查知识点:动态规划、最大递增子序列、动态内存分配

本题难度:中级

注意点:

1.输入参数为字符指针指向的字符串,需要先转换为整形数组,才能进行比较;

2.需要对入参进行判断

/*
功能:计算最少出列多少位同学,使得剩下的同学排成合唱队形
    
输入参数:
	 int N : 最初队列的N位同学 (2<=N<=50)
	 char* statureArray:N位同学的身高字符串(保证只含数字和空格)
	         身高Ti要求(130<=Ti<=230)
输出参数: 
	 int* rst: 最少出列多少位同学,使得剩下的同学排成合唱队形
返回值:
		0: 成功; -1:异常 
*/
/*解题思路:

首先计算每个数在最大递增子串中的位置

186  186  150  200  160  130  197  200   quene

1      1      1      2       2      1      3     4       递增计数


然后计算每个数在反向最大递减子串中的位置--->计算反向后每个数在最大递增子串中的位置

200  197  130  160  200  150  186  186   反向quene

1      1      1       2     3      2      3       3      递减计数


然后将每个数的递增计数和递减计数相加

186  186  150  200  160  130  197  200   quene

1      1      1      2       2     1      3      4       递增计数

3      3      2      3       2     1      1      1       递减计数

4      4      3      5       4     2      4      5       每个数在所在队列的人数+1(自己在递增和递减中被重复计算)


如160这个数

在递增队列中有2个人数

150  160

在递减队列中有2个人数

160  130

那么160所在队列中就有3个人

150  160  130


每个数的所在队列人数表达就是这个意思


总人数 - 该数所在队列人数 = 需要出队的人数


*/
int chorus(int N, char* StatureArray, int* Rst)
{
     if ((N < 2) || (N > 50) || (NULL == StatureArray) || ( NULL == Rst))//入参判断
	 {
		 return -1;
	 }
	int max = 0;
	/*int LIS[N];//最长递增子序列
	int LDS[N];//最长递减子序列*/
	int stu[20];
	memset(stu,0,sizeof(int)*20);//数组初始化
	for (int i = 0; i < N; i++)//将字符指针指向的字符串转化为整形数组
	{
		stu[i] = atoi(StatureArray + 4 * i);
	}
	int *LIS;
	LIS = (int *)malloc(N*sizeof(int));
	int *LDS;
	LDS = (int *)malloc(N*sizeof(int));
	for(int i=0;istu[j]&&LIS[j]+1>LIS[i])
			{
				LIS[i] = LIS[j]+1;
			}
		}
	}
	for(int i=N-1;i>=0;i--)
	{
		for(int j=N-1;j>i;j--)
		{
			if(stu[i]>stu[j]&&LDS[j]+1>LDS[i])
			{
				LDS[i] = LDS[j]+1;
			}
		}
	}
	for(int i=0;imax)
		{
			max = LIS[i]+LDS[i];
		}
	}
	*Rst = N - max +1;

	return 0;
}

get的知识点:

1.最大递增子序列:是指找到一个给定序列的最长子序列的长度,使得子序列中的所有元素单调递增

2.动态规划:https://www.zhihu.com/question/23995189

3.atoi()函数

atoi():int atoi(const char *str );

功能:把字符串转换成整型数。

str:要进行转换的字符串

返回值:每个函数返回 int 值,此值由将输入字符作为数字解析而生成。 如果该输入无法转换为该类型的值,则atoi的返回值为 0。

说明:当第一个字符不能识别为数字时,函数将停止读入输入字符串。
 

你可能感兴趣的:(华为机试108题)