#P2405. 第2题-幼儿园排队报数
          
                        
                                    
                      
        
              - 
          
          
                      2000ms
            
          
                      Tried: 645
            Accepted: 150
            Difficulty: 6
            
          
          
          
                       所属公司 : 
                              华为
                                
            
                        
              时间 :2022年10月12日-国内
                              
                      
          
 
- 
                        算法标签>暴力枚举          
 
第2题-幼儿园排队报数
题解描述
在这道题中,需要计算每个小朋友右侧比自己身高低的人的数量。这是一个典型的数组统计问题,可以通过暴力统计方法解决。
代码思路
暴力统计法的核心思想是:
- 从右到左遍历每一个小朋友,使用一个数组 
cnt来记录当前所有出现过的不同高度小朋友的数量。 - 每当遍历到一个新的小朋友时,通过数组 
cnt中的数据可以快速计算出比当前小朋友低的所有小朋友的数量。 - 由于小朋友的身高范围有限(40到110),因此我们可以利用一个定长的数组来存储每个身高出现的频次,从而避免复杂的数据结构并提升性能。
 
具体步骤如下:
- 输入数据:首先读取小朋友的数量 
n,然后读取每个小朋友的身高并存储在数组a中。 - 遍历并统计:从右向左遍历小朋友,记录当前小朋友的高度,将此高度计数加1,然后在计数数组 
cnt中统计出比当前小朋友低的所有身高的人数总和。 - 输出结果:结果存储在数组 
ans中,最后依次输出ans数组内容。 
时间复杂度
对于每个小朋友,统计比自己低的高度的操作在高度范围内(40到110,即70种不同的身高)循环一次。因此时间复杂度为 (O(n \times h)),其中 (h) 为可能的身高值数量,即常数 70。所以,整体复杂度约为 (O(n)),性能可以满足要求。
C++代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int a[N];        // 每个小朋友的高度
int cnt[200];    // 每个高度的小朋友个数
int ans[N];      // 最后答案
int n;
int main() {
    cin >> n;
    for(int i = 1; i <= n; i++) {
        cin >> a[i];        // 输入每个小朋友的高度
    }
    
    // 从右向左遍历所有小朋友
    for(int i = n; i > 0; i--) {        
        cnt[a[i]]++;        // 更新当前小朋友高度的计数
        for(int j = 40; j < a[i]; j++) {
            ans[i] += cnt[j];        // 累加比当前小朋友低的所有小朋友个数
        }
    }
    
    // 输出最终结果
    for(int i = 1; i <= n; i++) {
        cout << ans[i] << " \n"[i == n];  // 输出结果,并避免行末空格
    }
}
Python代码
# 输入数据
n = int(input())
a = list(map(int, input().split()))
# 初始化每个身高小朋友的计数和结果数组
cnt = [0] * 200
ans = [0] * n
# 从右向左遍历
for i in range(n - 1, -1, -1):
    cnt[a[i]] += 1  # 更新当前小朋友的身高计数
    # 统计比当前小朋友身高低的数量
    ans[i] = sum(cnt[j] for j in range(40, a[i]))
# 输出结果
print(" ".join(map(str, ans)))
Java代码
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        
        int[] a = new int[n + 1];  // 存储每个小朋友的身高
        int[] cnt = new int[200];  // 记录每个高度的出现次数
        int[] ans = new int[n + 1]; // 存储每个小朋友的报数结果
        // 输入每个小朋友的身高
        for (int i = 1; i <= n; i++) {
            a[i] = scanner.nextInt();
        }
        // 从右向左遍历小朋友
        for (int i = n; i > 0; i--) {
            cnt[a[i]]++;  // 更新当前小朋友身高的计数
            // 计算比当前小朋友低的身高数量
            for (int j = 40; j < a[i]; j++) {
                ans[i] += cnt[j];
            }
        }
        // 输出报数结果
        for (int i = 1; i <= n; i++) {
            System.out.print(ans[i] + (i == n ? "\n" : " "));
        }
        scanner.close();
    }
}
说明
- 数组 
cnt:用于记录每种身高出现的频次,从而可以直接查询到比当前身高小的所有小朋友的数量。 - 遍历顺序:从右向左遍历,以便在统计过程中能够依次更新右侧的身高信息。
 - 高度范围处理:身高的最小值是 40,因此在循环统计低于当前身高的小朋友数量时从 40 开始。这里假设高度的上限不会超过 200,从而将 
cnt定义为长度 200。 
这种方法利用身高范围的限制和哈希表统计,从而使复杂度控制在 (O(n)) 左右,可以应对较大的数据输入。
题目内容
小明是一位幼儿园院长,他是一位富有经验和激情的教育专业人士。他对幼儿教育充满热情,致力于为幼儿提供最佳的教育和关爱。
作为幼儿园院长,小明在幼儿园的管理和运营方面有着丰富的经验。他深刻理解幼儿的成长和发展需要,关注每一个幼儿的个性和特点,并积极引导他们在安全、温馨、富有启发性的学习环境中成长。
今年春季,小明幼儿园开课了。开春小朋友入学报名参加互联网各大厂的春招。小朋友都排好队。但小朋友的身高有高有低,所以塔老师让所有小朋友报数:以自身为基准向队尾看,有几个比自己矮的小朋友就报几
换句话说:给定整数数组 nums 即为排队的小朋友,要求返回新的数组 counts , counts[i] 为小朋友的报数
输入描述
第一行是数组长度 N
第二行是幼儿园小朋友的队列,一个长度 N 的整型数组
1≤nums.length≤105 , 40≤nums[i]≤110
counts.length=nums.length
输出描述
新的整型数组,数组元素是输入中对应位置小朋友的报数
样例
输入
5
81 82 76 75 100
输出
2 2 1 0 0
样例解释:
81 的右侧有2个更小的元素(76,75)
82 的右侧有2个更小的元素(76,75)
76 的右侧仅有1个更小的元素(75)
75 的右侧没有更小的元素
100 的也右侧没有更小的元素