名企算法与数据结构题目最优解—部分问题总结之七—1

分糖果问题

题目

一群孩子做游戏,请根据游戏得分分发糖果,要求如下:
1、不管每个孩子得分多少,起码分到一个糖果
2、任意两个相邻的孩子之间,得分较多的孩子必须拿多一些的糖果。
给定一个数组arr代表得分数组,请返回最少需要多少糖果。
例如:arr = [1,2,2],分配情况为[1,2,1],满足要求且数量最少,返回4
进阶题目
在原题基础上加一条规则:
3、任意两个相邻的孩子之间如果得分一样,糖果数必须相同。
如:arr=[1,2,2],糖果分配为[1,2,2],返回5
要求长度为N,原题与进阶时间复杂度都为O(N),额外空间复杂度为O(1)

代码

#include<iostream>
#include<algorithm>
using namespace std;

int rightCandies(int* arr, int left, int right)
{
   
	int n = right - left + 1;
	return n + n * (n - 1) / 2;
}

int nextMinIndex1(int* arr, int len, int start)
{
   
	for (int i = start; i < len - 1; i++)
	{
   
		if (arr[i] <= arr[i + 1])
			return i;
	}
	return len - 1;
}

int candy1(int* arr, int len)
{
   
	if (arr == NULL || len < 1)
		return 0;
	int index = nextMinIndex1(arr, len, 0);
	int res = rightCandies(arr, 0, index++);
	int lbase = 1;
	int next = 0;
	int rcandies = 0;
	int rbase = 0;
	while (index != len)
	{
   
		if (arr[index] > arr[index - 1])
		{
   
			res += ++lbase;
			index++;
		}
		else if (arr[index] < arr[index - 1])
		{
   
			next = nextMinIndex1(arr, len, index - 1);
			rcandies = rightCandies(arr, index - 1, next++);
			rbase = next - index + 1;
			res += rcandies + (rbase > lbase ? -lbase : -rbase);
			lbase = 1;
			index = next;
		}
		else
		{
   
			res += 1;
			lbase = 1;
			index++;
		}
	}
	return res;
}

/*相同的坡顶获得的糖果的个数相同*/
int* rightCandiesAndBase(int* arr, int left, int right)
{
   
	int base = 1;
	int candies = 1;
	for (int i = right - 1; i >= left; i--)
	{
   
		if (arr[i] == arr[i + 1])
			candies += base;
		else
			candies += ++base;
	}
	int* res = new int[2];
	res[0] = candies; res[1] = base;
	return res;
}

int nextMinIndex2(int* arr, int len, int start)
{
   
	for (int i = start; i != len - 1; i++)
	{
   
		if (arr[i] < arr[i + 1])
			return i;
	}
	return len - 1;
}

int candy2(int* arr, int len)
{
   
	if (arr == NULL || len == 0)
		return 0;
	int index = nextMinIndex2(arr, len, 0);
	int* data = new int[2];
	data = rightCandiesAndBase(arr, 0, index++);  //开头部分是否存在右坡
	int res = data[0];
	int lbase = 1;
	int same = 1;
	int next = 0;
	while (index != len)
	{
   
		if (arr[index] > arr[index - 1])
		{
   
			res += ++lbase;
			same = 1;
			index++;
		}
		else if (arr[index] < arr[index - 1])
		{
   
			next = nextMinIndex2(arr, len, index - 1);
			data = rightCandiesAndBase(arr, index - 1, next++);
			if (data[1] <= lbase)
				res += data[0] - data[1];
			else
				res += -lbase * same + data[0] - data[1] + data[1] * same;
			index = next;
			lbase = 1;
			same = 1;
		}
		else
		{
   
			res += lbase;
			same++;
			index++;
		}
	}
	return res;
}

int main()
{
   
	int len;
	cin >> len;
	int* scores = new int[len];
	for (int i = 0; i < len; i++)
		cin >> scores[i];
	//int minNum = candy1(scores, len);
	int minNum = candy2(scores, len);
	cout << minNum << endl;
	getchar();
	return 0;
}

一种消息接收并打印的结构设计

题目

消息流吐出2,一种结构接收而不打印2,因为1还未出现;
消息流吐出1,一种结构接受1,并打印:1,2;
消息流吐出4,一种结构接收而不打印4,因为3还未出现;
消息流吐出5,一种结构接收而不打印5,因为3还未出现;
消息流吐出7,一种结构接收而不打印7,因为3还未出现;
消息流吐出3,一种结构接受3,并打印:3,4,5;
消息流吐出9,一种结构接收而不打印9,因为6还未出现;
消息流吐出8,一种结构接收而不打印8,因为6还未出现;
消息流吐出6,一种结构接受6,并打印:6,7,8,9;
已知一个消息流会不断吐出整数1~N,不一定按顺序吐出。如果上次打印的数位i,当i+1出现时,答应i+1及之后接收过并连续的所有数字,直到1-N全部打印完,设计并实现这种结构。
时间复杂度为O(N)

代码

#include<iostream>
#include<algorithm>
#include<map>
using namespace std;

struct node {
   
	int num;
	node* next;
	node(int val) : num(val),next(NULL)
	{
   

	}
};

class messageBox {
   
private:
	map<int, node*>headMap;
	map<int, node*>tailMap;
	int lastPrint;
	void print();
public:
	messageBox();
	void receive(int num);
	
};

messageBox::messageBox()
{
   
	lastPrint = 0;
}

void messageBox::receive(int num)
{
   
	if (num < 1)
		return;
	node* cur = new node(num);
	headMap[num] = cur;
	tailMap[num] = cur;
	if (tailMap.find(num - 1) != tailMap.end())
	{
   
		tailMap[num - 1]->next = cur;
		tailMap.erase(num - 1);
		headMap.erase(num);
	}
	if (headMap.find(num + 1) != headMap.end())
	{
   
		cur->next = headMap[num + 1];
		tailMap.erase(num);
		headMap.erase(num + 1);
	}
	if (headMap.find(lastPrint + 1) != headMap.end())
		print();
}

void messageBox::print()
{
   
	node* Node = headMap[++lastPrint];
	headMap.erase(lastPrint);
	while (Node != NULL)
	{
   
		cout << Node->num << 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值