一先来每日一题
在一个仓库里,有一排条形码,其中第 i 个条形码为 barcodes[i]。
请你重新排列这些条形码,使其中任意两个相邻的条形码不能相等。 你可以返回任何满足该要求的答案,此题保证存在答案。
示例 1:
输入:barcodes = [1,1,1,2,2,2]
输出:[2,1,2,1,2,1]
示例 2:
输入:barcodes = [1,1,1,1,2,2,3,3]
输出:[1,3,1,3,2,1,2,1]
提示:
1 <= barcodes.length <= 10000
1 <= barcodes[i] <= 10000
通过次数20,401提交次数46,900
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/distant-barcodes
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
这题目,要的就是对堆的排序,对出现的数进行统计
转化成堆
我们应当把最多的最先排,排了一个后更新堆,再拿最多的,但是要判断和上一 个是不是一样的
如果一样的,我们就取第二多的来排,每次排完之后要更新,堆
我们建堆,不需要建立啥完整的东西,我们只需要一个上滤或者下滤,因为不需要出堆,堆形成后不会有任何的增加或者减少
所以工作量不大,还是可以接受的
代码
typedef struct node{
int num;
int size;
}squrt;
squrt dui[100100];
int duisize=1;
void down(int x){//下滤
if(x*2<duisize)
if(dui[x].size<dui[2*x].size){
squrt k=dui[x];
dui[x]=dui[2*x];
dui[2*x]=k;
down(2*x);
}
if(x*2+1<duisize)
if(dui[x].size<dui[2*x+1].size){
squrt k=dui[x];
dui[x]=dui[2*x+1];
dui[2*x+1]=k;
down(2*x+1);
}
}
//向下滤
int* rearrangeBarcodes(int* barcodes, int barcodesSize, int* returnSize){
int a[100100]={0};
int map[100100]={0};
*returnSize=barcodesSize;
int* ans=(int*)malloc(sizeof(int)*100100);
for(int j=0;j<barcodesSize;j++){
a[barcodes[j]]++;
}
for(int j=0;j<barcodesSize;j++){
if(a[barcodes[j]]!=0&&map[barcodes[j]]==0){
map[barcodes[j]]=1;
dui[duisize].num=barcodes[j];
dui[duisize].size=a[barcodes[j]];
duisize++;
}
}//统计
for(int j=duisize-1;j>=1;j--){
if(j<=duisize/2){
down(j);
}
}//下滤建堆
ans[0]=dui[1].num;
dui[1].size--;
down(1);
for(int m=1;m<barcodesSize;m++){
if(ans[m-1]!=dui[1].num){
ans[m]=dui[1].num;
dui[1].size--;
down(1);
}
else{//第二的肯定是堆顶的右儿子或者是左儿子
if(dui[2].size>=dui[3].size){
ans[m]=dui[2].num;
dui[2].size--;
down(2);
}
else{
ans[m]=dui[3].num;
dui[3].size--;
down(3);
}
}
}
return ans;
}
小孩爱吃糖
Description
幼儿园里面有n 个孩子,老师让这n个孩子站成一排。
定义一个整数数组 a[n]表示每个孩子的评分。
你需要按照以下要求,给这些孩子分发糖果:
每个孩子至少分配到 1 个糖果。
相邻两个孩子评分更高的孩子会获得更多的糖果。
请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。
Input
第一个行输入一个n,代表有n个孩子(1 <= n <= 2 * 10^4)
第二行输入n个数,表示每个孩子的评分(0 <= a[i] <= 2 * 10^4)
Output
输出仅一行,表示需要准备的 最少糖果数目
Sample Input 1
3 1 0 2
Sample Output 1
5
Sample Input 2
3 1 2 2
Sample Output 2
4
Hint
对于第一个样例,你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。 对于第二个样例,你可以分别给第一个、第二个、第三个孩子分发 1、2、1 颗糖果。
这题目,思路想想还是简单的,
我们可以得到信息,我要是比左边的大我得到的糖果至少比他大一
我要死是比右边的大我得到的糖果就比他大一
那我们从左边来遍历一遍,这个比前面的大就是他加1(最少)
从右边也来一次
就可以了
把数组相加,就可以得到答案了
#include<stdio.h>
int main(){
int n;
int a[10000];
int ans[10000];
ans[1]=1;
scanf("%d",&n);
for(int j=1;j<=n;j++){
scanf("%d",&a[j]);
}
for(int j=2;j<=n;j++){
if(a[j]>a[j-1]){
ans[j]=ans[j-1]+1;
}
else{
ans[j]=1;
}
}
for(int k=n-1;k>=1;k--){
if(a[k]>a[k+1]){
ans[k]=ans[k+1]+1;
}
}
int sum=0;
for(int k=n;k>=1;k--)
sum+=ans[k];
printf("%d",sum);
}
这是二叉搜索树吗?
Description
一棵二叉搜索树可被递归地定义为具有下列性质的二叉树:对于任一结点,
- 其左子树中所有结点的键值小于该结点的键值;
- 其右子树中所有结点的键值大于等于该结点的键值;
- 其左右子树都是二叉搜索树。
所谓二叉搜索树的“镜像”,即将所有结点的左右子树对换位置后所得到的树。
给定一个整数键值序列,现请你编写程序,判断这是否是对一棵二叉搜索树或其镜像进行前序遍历的结果。
Input
输入的第一行给出正整数N(≤1000)。随后一行给出N个整数键值,其间以空格分隔。
Output
如果输入序列是对一棵二叉搜索树或其镜像进行前序遍历的结果,则首先在一行中输出YES
,然后在下一行输出该树后序遍历的结果。数字间有 1 个空格,一行的首尾不得有多余空格。若答案是否,则输出NO
。
Sample Input 1
7 8 6 5 7 10 8 11
Sample Output 1
YES 5 7 6 8 11 10 8
Sample Input 2
7 8 6 8 5 10 9 11
Sample Output 2
NO
注意,如果是镜像树的话是输出镜像树的后序遍历
判断是不是二叉搜索树的方法就是,左子树比我小右子树比我大
7
8 6 5 7 10 8 11
如上
6 5 7 比8 小就是左树 10 大于8其和其后面的就是右子树\
不能成树的情况就是 8 6 5 7 10 7 11 第一个比根大的点后面还有比根小的
这不符合 右子树都比根大的定义
镜像就是反过来,就是定义也反了,判断和上面是一样的
在判断遍历的时候,可把节点压入栈中,遍历完确定性质符合就可以直接输出
但是压入的方式 要注意确保输出的是后序(自己给自己增加了难度,,,,)
两种树只要符合其中的一种就可以了
代码
#include<stdio.h>
#include<stdlib.h>
int a[10010] = { 0 };
int rsl = 1;
int dsl = 1;//刚开始都认为是正确的
int n;
typedef struct node {
int a;
struct node* l;
struct node* r;
}Node;
typedef struct {
Node* root;
}Tree;
typedef struct sq {
int data[1010];
int length;
}sqt;//栈输出后序的辅助结构
void push(int e, sqt& s) {
s.data[s.length] = e;
s.length++;
}
int pop(sqt& s) {
if (s.length > 0) {
s.length--;
return s.data[s.length];
}
else {
return -1;
}
}
void pan1(int p, int l, int r, sqt& s1) {
int kl = 0;
int rs = r + 1;//右子树的根节点
for (int h = l;h <= r;h++) {
if (a[h] >= p && kl == 0) {
rs = h;
push(a[rs], s1);
kl = 1;
}
if (kl == 1 && a[h] < p) {
rsl = 0;
return;
}
}
int ls; //左边
if (a[l] < p) {
ls = l;
}
else {
ls = r + 1;
}
if (rs + 1 <= r) {
pan1(a[rs], rs + 1, r, s1);
}
if (ls == l) {
push(a[ls], s1);
}
if (ls + 1 <= rs - 1) {
pan1(a[ls], ls + 1, rs - 1, s1);
}
}
void pan2(int p, int l, int r, sqt& s2) {
int kl = 0;
int ls;//左子树的根节点
int rs = r + 1;//右子树的根节点
for (int h = l;h <= r;h++) {
if (a[h] < p && kl == 0) {
rs = h;
push(a[rs], s2);
kl = 1;
}
if (kl == 1 && a[h] >= p) {
dsl = 0;
return;
}
}
if (a[l] >= p) {
ls = l;
}
else {
ls = r + 1;
}
if (rs + 1 <= r) {
pan2(a[rs], rs + 1, r, s2);
}
if (ls == l) {
push(a[ls], s2);
}
if (ls + 1 <= rs - 1) {
pan2(a[ls], ls + 1, rs - 1, s2);
}
}
int main() {
scanf("%d", &n);
for (int j = 1;j <= n;j++)
scanf("%d", &a[j]);
sqt s1, s2;
s1.length = 0;
s2.length = 0;
push(a[1], s1);
push(a[1], s2);
pan1(a[1], 2, n, s1);
pan2(a[1], 2, n, s2);
if (rsl == 1 || dsl == 1) {
printf("YES\n");
if (rsl == 1) {
while (s1.length != 0) {
int j = pop(s1);
printf("%d", j);
if (s1.length != 0) {
printf(" ");
}
}
}
else if (dsl == 1) {
while (s2.length != 0) {
int j = pop(s2);
printf("%d", j);
if (s2.length != 0) {
printf(" ");
}
}
}
}
else {
printf("NO");
}
return 0;
}
最好可以在本子上面画画看看到底压入栈是咋搞的,便于理解如果是选择建树来输出的话,可能比这要简单易懂的多
洛希极限
Description
科幻电影《流浪地球》中一个重要的情节是地球距离木星太近时,大气开始被木星吸走,而随着不断接近地木“刚体洛希极限”,地球面临被彻底撕碎的危险。但实际上,这个计算是错误的。
洛希极限(Roche limit)是一个天体自身的引力与第二个天体造成的潮汐力相等时的距离。当两个天体的距离少于洛希极限,天体就会倾向碎散,继而成为第二个天体的环。它以首位计算这个极限的人爱德华·洛希命名。(摘自百度百科)
大天体密度与小天体的密度的比值开 3 次方后,再乘以大天体的半径以及一个倍数(流体对应的倍数是 2.455,刚体对应的倍数是 1.26),就是洛希极限的值。例如木星与地球的密度比值开 3 次方是 0.622,如果假设地球是流体,那么洛希极限就是0.622×2.455=1.52701倍木星半径;但地球是刚体,对应的洛希极限是0.622×1.26=0.78372倍木星半径,这个距离比木星半径小,即只有当地球位于木星内部的时候才会被撕碎,换言之,就是地球不可能被撕碎。
本题就请你判断一个小天体会不会被一个大天体撕碎。
Input
输入在一行中给出 3 个数字,依次为:大天体密度与小天体的密度的比值开 3 次方后计算出的值(≤1)、小天体的属性(0 表示流体、1 表示刚体)、两个天体的距离与大天体半径的比值(>1但不超过 10)。
Output
在一行中首先输出小天体的洛希极限与大天体半径的比值(输出小数点后2位);随后空一格;最后输出^_^
如果小天体不会被撕碎,否则输出T_T
。
Sample Input 1
0.622 0 1.4
Sample Output 1
1.53 T_T
Sample Input 2
0.622 1 1.4
Sample Output 2
0.78 ^_^
好啊
妥妥的水题(呜呜呜呜呜)
上代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(){
double ll=0,kk=0,oo=1.26;
int jj=0;
scanf("%lf",&ll);
scanf("%d",&jj);
scanf("%lf",&kk);
if(jj==0)
oo=2.455;
double ans=ll*oo;
printf("%0.2lf",ans);
if(ans<kk){
printf("^_^");
}
else{
printf("T_T");
}
return 0;
}
ok,我还有题目要理解一下,关于动态线段树的理解
以及背包,我还没完全吃透讲不出来
让我给它研究一会再讲
还有,我要学c++,每次打数据结构要打好久啊
痛真的太痛了
ok撒花谢幕
bb