PAT (Basic Level) 1023 组个最小数 (20 point(s))

// 未精简
#include <bits/stdc++.h>
using namespace std;

int main() {
    int  n;
    map <int, int> number;
    // 输入 0->9 数字i 用map存放数字数量
    for(int i = 0; i <= 9; i++){
        cin >> n;
        number[i] = n;
    }
    // cout << number.size();
    bool first = false;
    // 第一位不能输出0 其他按照map的小到大顺序输出
    for(auto num = number.begin(); ;++num){
        if(num->first == 0)
            continue;
        if(num->second != 0){
            cout << num->first;
            num->second--;
            break;
        }
    }
    for(auto num : number){
        // 获取val作为循环次数 输出key
        for(int i = 0; i < num.second; i++)
            cout << num.first;
    }
}
// 精简后
#include <bits/stdc++.h>
using namespace std;
int main() {
    int cnt;
    map<int, int> num;
    // 从数字0开始读取
    for(int i = 0; i <= 9; i++){
        cin >> cnt;
        // 跳过0个数
        if(cnt != 0)
            num[i] = cnt;
    }
    // 当0存在时 跳过数字0 输出合法数字首位
    auto n = num.begin();
    if(n->first == 0) cout << (++n)->first, n->second--;
    // 遍历并输出
    for(auto& n : num)
        while(n.second--)
            cout << n.first;
}

if(cnt != 0)
            num[i] = cnt;

这跟前面的 1015 德才论 读取有点相似,从输出样例可以看到,数字的出现次数为 0 不需要输出的,同理德才论那题没达到 L 的最低录取线也是不需要考虑的。所以这里做一个判断,当输入的数为 0 的时候就跳过这个数。


auto n = num.begin();

 for(auto& n : num)

这两个刚才搞混了,想了半天用指针指向容器的时候不是直接写一个变量名就可以的吗。看了下,原来用指针的 = 赋值的时候,需要用 begin() 来返回首地址才行。而 foreach 不需要直接写一个变量名就可以。 


if(n->first == 0) cout << (++n)->first, n->second--;

至少拥有 1 个非 0 的数字 

原本写的时候因为把全部数字都读进来了,所以还想了一个循环来遍历每一个数字 key。但因为前面跳过了次数 0 的数字,所以直接用迭代器 ++ 就可以指向下一个非 0 的数字。

同时要注意题目这里说的至少一个非 0 数,也就是 1 ~ 9,但意味着可能没有数字 0。如果没有0就不需要跳过了。

所以代码首先要判断是否存在数字 0 ,如果存在则跳到下一个非零的key,同时个数 -- 。


(++n)->first 

++n->first  

当 n 是一个结构体或者指针的时候,如果想让这个对象先运算移动位置后取对象的值,就得用括号把运算和对象括起来(上)。因为点运算符 (.)箭头运算符 (->) 与自增 (++) 自减 (--) 运算符相比,前者的运算级别最高,所以当他们放在一起而不加括号的时候(下)会采用右到左的顺序,先读取对象,再对对象运算。

 C语言中运算符优先级记忆方法


n.second--  

for(auto& n : num) 

当时想了想不记得迭代器是否可以对 val 个数进行运算了,所以写成读取 val 用作循环来输出。参考代码这里说明迭代器确实可以对 val 个数进行运算。

本来说如果要用 val 作为循环变量的时候,需要用 & 取引用来对原容器的 val 进行更改的,不然 val 作为循环变量不会改变。但删去 & 之后发现并没有影响,结果照样AC,不太明白原理。所以做了如下测试。

 

可以看到,当不取有 & 引用的时候,再次输出容器里 val 是正常的,而当取引用之后,再次输出就可以看到对原容器 val 改变的结果。

所以当时应该是想错了,auto类型推导的应该是此处 num<int> 的 int ,当第一行的 for(auto & n : num)  时会得到 num 容器的 val 赋予给 auto 类型的 n 对象。而这时就能够在第二行的 while 中作循环变量直到等于 val = 0 的时候结束,重新到第一行 foreach 读取下一个val。

参考代码        for(auto a:b)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值