文章目录
分糖果问题
题目
一群孩子做游戏,请根据游戏得分分发糖果,要求如下:
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 <<