PAT (Basic Level) Practice 刷题笔记(2)

第一题

在这里插入图片描述

笔记:

  1. 要判断一个数是不是关键数其实可以理解为看有没有被其他的数“经过”,因为每一个数都会最终回到1,在这期间会经过一些数字,如果这个数字被经过了,那它就被覆盖了,也就不是关键数了。
  2. 理解了关键之后,就很好写了,只需要分别让待验证的数回到1,对途中经过的每一个数进行标记,当每一个待验证的数都走到1之后,判断待验证的数是否被标记过,如果被标记过,则不是关键数,反之则为关键数。
  3. 冒泡排序有点生疏了,再熟悉一下:
for (int i = 0; i < len - 1; ++i) {
        for (int j = 0; j < len - i - 1; ++j) {
            if (res[j] < res[j + 1]){
                swap(res[j],res[j + 1]);
            }
        }
    }

我的代码:

不知道为什么有两个测试点过不了…(sos)

  • 我现在明白了,原来我冒泡排序写错了!!!
#include <iostream>
using namespace std;

void swap(int &a, int &b){
    int hold;
    hold = a;
    a = b;
    b = hold;
}

int  main( ){
    int n,m;
    int len = 0;
    int arr[1000];
    int flag[1000] = {0};
    int res[1000] = {0};
    cin>>n;
    for (int i = 0; i < n; ++i) {
        cin>>arr[i];
    }
    for (int i = 0; i < n; ++i) {
        m = arr[i];
        if (flag[i] == 1){
            continue;
        }
        while(m != 1){
            if (m % 2 == 0){
                m /= 2;
            }
            else{
                m = (3 * m + 1) / 2;
            }
            for (int j = 0; j < n; ++j) {
                if (m == arr[j]){
                    flag[j] = 1;
                }
            }
        }
    }

    for (int i = 0; i < n; ++i) {
        if (flag[i] == 0){
            res[len] = arr[i];
            len++;
        }
    }
    for (int i = 0; i < len - 1; ++i) {
        for (int j = 0; j < len - i - 1; ++j) {
            if (res[j] < res[j + 1]){
                swap(res[j],res[j + 1]);
            }
        }
    }

    for (int i = 0; i < len; ++i) {
        cout<<res[i];
        if (i != len - 1){
            cout<<" ";
        }
        else cout<<endl;
    }
}

别人的代码:

她的算法和我基本一致,不同的是用了vector

#include <vector>
#include <algorithm>
using namespace std;
int arr[10000];
bool cmp(int a, int b) {return a > b;}
int main() {
    int k, n, flag = 0;
    cin >> k;
    vector<int> v(k);
    for (int i = 0; i < k; i++) {
        cin >> n;
        v[i] = n;
        while (n != 1) {
            if (n % 2 != 0) n = 3 * n + 1;
            n = n / 2;
            if (arr[n] == 1) break;
            arr[n] = 1;
        }
    }
    sort(v.begin(), v.end(), cmp);
    for (int i = 0; i < v.size(); i++) {
        if (arr[v[i]] == 0) {
            if (flag == 1) cout << " ";
            cout << v[i];
            flag = 1;
        }
    }
    return 0;
}

第二题

在这里插入图片描述

笔记

  1. 这道题看着挺简单,但是有一些逻辑关系还是挺难理清楚的,想了半天才搞清楚。
  2. 首先我用字符数组保存数字,然后循环应该从高位往下进行,循环里的每一位通过减去‘0’得出该位的数值,然后再循环n次输出相应的字符。这是基本的想法
  3. 但是输入的数字并不一定是三位的,所以外层循环i应该从3 - strlen(arr)开始,里面再根据i的数值判断对应的位数。
  4. 内层循环用于输出字符,也应该根据i的不同改变循环的次数。

我的代码:

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

int  main( ){
    char arr[10];
    cin>>arr;
    for (int i = 3 - strlen(arr); i < 3; ++i) {
        if (i == 0){
            for (int j = 0; j < arr[i - (3 - strlen(arr))] - '0';++j) {
                cout<<'B';
            }
        }
        if (i == 1){
            for (int j = 0; j < arr[i - (3 - strlen(arr))] - '0'; ++j) {
                cout<<'S';
            }
        }
        if (i == 2){
            for (int j = 1; j <= arr[i - (3 - strlen(arr))] - '0'; ++j) {
                cout<<j;
            }
        }
    }
    cout<<endl;
}

第三题

在这里插入图片描述

笔记:

  1. 我的想法是建一个比原来长的数组,然后按要求往后移m位,然后再写一个循环,将长于原数组的元素依次放进前面空的地方。
  2. 题目给的测试样例没有问题,但是有几个测试点过不了

我的代码:

#include <iostream>
using namespace std;
int main(){
    int n,m;
    int flag[1000] = {0};
    int arr[1000];
    cin>>n>>m;
    for (int i = 0; i < n; ++i) {
        cin>>arr[i];
    }
    for (int i = n - 1; i >= 0; --i) {
        arr[i + m] = arr[i];
        flag[i + m] = 1;
    }
    for (int i = n; i <= n - 1 + m; ++i) {
        arr[i - n] = arr[i];
    }
    for (int i = 0; i < n; ++i) {
        cout<<arr[i];
        if (i != n - 1){
            cout<<" ";
        }
        else{
            cout<<endl;
        }
    }
}

别人的代码:

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
    int n, m;
    cin >> n >> m;
    vector<int> a(n);
    for (int i = 0; i < n; i++)
        cin >> a[i];
    m %= n;
    if (m != 0) {
        reverse(begin(a), begin(a) + n);
        reverse(begin(a), begin(a) + m);
        reverse(begin(a) + m, begin(a) + n);
    }
    for (int i = 0; i < n - 1; i++)
        cout << a[i] << " ";
    cout << a[n - 1];
    return 0;
}

大佬的分析:

分析:数组长度为n,要想把数组循环右移m位,只需要先将整个数组a倒置,再将数组前m位倒置,最后将数组后n-m位倒置即可完成循环右移m位~reverse函数可以实现将一个数组或者vector中元素倒置,这个函数在algorithm头文件中~(如果m大于n,那么循环右移m位相当于循环右移m%n位,因为那些n倍数位的移动是多余的,所以在使用m之前,先将m = m%n)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值