PAT算法题学习笔记

1001. 害死人不偿命的(3n+1)猜想 (15)

卡拉兹(Callatz)猜想:

对任何一个自然数n,如果它是偶数,那么把它砍掉一半;如果它是奇数,那么把(3n+1)砍掉一半。这样一直反复砍下去,最后一定在某一步得到n=1。卡拉兹在1950年的世界数学家大会上公布了这个猜想,传说当时耶鲁大学师生齐动员,拼命想证明这个貌似很傻很天真的命题,结果闹得学生们无心学业,一心只证(3n+1),以至于有人说这是一个阴谋,卡拉兹是在蓄意延缓美国数学界教学与科研的进展……

我们今天的题目不是证明卡拉兹猜想,而是对给定的任一不超过1000的正整数n,简单地数一下,需要多少步(砍几下)才能得到n=1?

输入格式:每个测试输入包含1个测试用例,即给出自然数n的值。

输出格式:输出从n计算到1需要的步数。

输入样例:
3
输出样例:
5

#include <iostream>

using namespace std;

int foo(int n, int stepNum) {

    if (n == 1)
        return stepNum;
    else
        ++stepNum;

    if (n % 2 == 0)
        return foo(n/2, stepNum);
    else
        return foo((3*n+1)/2, stepNum);
}



int main() {
    int stepNum = 0, n;
    cin >> n;

    int r = foo(n, stepNum);
    cout << r << endl;
    return 0;
}

1002. 写出这个数 (20)

读入一个自然数n,计算其各位数字之和,用汉语拼音写出和的每一位数字。

输入格式:每个测试输入包含1个测试用例,即给出自然数n的值。这里保证n小于10^100。

输出格式:在一行内输出n的各位数字之和的每一位,拼音数字间有1 空格,但一行中最后一个拼音数字后没有空格。

输入样例:
1234567890987654321123456789
输出样例:
yi san wu

var f = (num) => {
    let result = num.toString()
                    .split('')
                    .map((c) => parseInt(c))
                    .reduce((x, y) => x + y)
                    .toString()
                    .split('')
                    .map((c) => {
                        switch (c) {
                            case '0':
                                return 'ling'; break;
                            case '1':
                                return 'yi'; break;
                            case '2':
                                return 'er'; break;
                            case '3':
                                return 'san'; break;
                            case '4':
                                return 'si'; break;
                            case '5':
                                return 'wu'; break;
                            case '6':
                                return 'liu'; break;
                            case '7':
                                return 'qi'; break;
                            case '8':
                                return 'ba'; break;
                            case '9':
                                return 'jiu'; break;
                        }
                    })
                    .join(' ');
    return result;
};

1006. 换个格式输出整数 (15)

让我们用字母B来表示“百”、字母S表示“十”,用“12...n”来表示个位数字n(<10),换个格式来输出任一个不超过3位的正整数。例如234应该被输出为BBSSS1234,因为它有2个“百”、3个“十”、以及个位的4。

输入格式:每个测试输入包含1个测试用例,给出正整数n(<1000)。

输出格式:每个测试用例的输出占一行,用规定的格式输出n。

输入样例1:
234
输出样例1:
BBSSS1234
输入样例2:
23
输出样例2:
SS123

var f = (num) => {
    let numArr = num.toString()
                    .split('')
                    .map((c) => parseInt(c));
    numArr[0] = new Array(numArr[0]+1).join('B');
    numArr[1] = new Array(numArr[1]+1).join('S');
    numArr[2] = '123456789'.substr(0, numArr[2]);

    return numArr.join('');

};

1008. 数组元素循环右移问题 (20)

一个数组A中存有N(N>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(M>=0)个位置,即将A中的数据由(A0 A1……AN-1)变换为(AN-M …… AN-1 A0 A1……AN-M-1)(最后M个数循环移至最前面的M个位置)。如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?

输入格式:每个输入包含一个测试用例,第1行输入N ( 1<=N<=100)、M(M>=0);第2行输入N个整数,之间用空格分隔。

输出格式:在一行中输出循环右移M位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。

输入样例:
6 2
1 2 3 4 5 6
输出样例:
5 6 1 2 3 4

function reverse(arr, left, right) {
    var i, j, temp;
    for (i = left, j = right; i < j; ++i, --j) {
        temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

// 数组循环右移m位
function f (arr, m) {
    rear = arr.length - 1;
    reverse(arr, 0, rear);
    reverse(arr, 0, m - 1);
    reverse(arr, m, rear);
}

1009. 说反话 (20)

给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出。

输入格式:测试输入包含一个测试用例,在一行内给出总长度不超过80的字符串。字符串由若干单词和若干空格组成,其中单词是由英文字母(大小写有区分)组成的字符串,单词之间用1个空格分开,输入保证句子末尾没有多余的空格。

输出格式:每个测试用例的输出占一行,输出倒序后的句子。

输入样例:
Hello World Here I Come
输出样例:
Come I Here World Hello

function f (str) {
    return str.split(' ').reverse().join(' ');
}

1016. 部分A+B (15)

正整数A的“DA(为1位整数)部分”定义为由A中所有DA组成的新整数PA。例如:给定A = 3862767,DA = 6,则A的“6部分”PA是66,因为A中有2个6。

现给定A、DA、B、DB,请编写程序计算PA + PB。

输入格式:

输入在一行中依次给出A、DA、B、DB,中间以空格分隔,其中0 < A, B < 1010。

输出格式:

在一行中输出PA + PB的值。

输入样例1:
3862767 6 13530293 3
输出样例1:
399
输入样例2:
3862767 1 13530293 8
输出样例2:
0

function f (a, da, b, db) {
    let arrA = a.toString().match(new RegExp(da, 'g'));
    let arrB = b.toString().match(new RegExp(db, 'g'));

    let numA = 0,
        numB = 0;
    if (arrA) // 如果arrA不为null
        numA = parseInt(arrA.join(''));
    if (arrB)
        numB = parseInt(arrB.join(''));

    return numA + numB;
}

1023. 组个最小数 (20)

给定数字0-9各若干个。你可以以任意顺序排列这些数字,但必须全部使用。目标是使得最后得到的数尽可能小(注意0不能做首位)。例如:给定两个0,两个1,三个5,一个8,我们得到的最小的数就是10015558。

现给定数字,请编写程序输出能够组成的最小的数。

输入格式:

每个输入包含1个测试用例。每个测试用例在一行中给出10个非负整数,顺序表示我们拥有数字0、数字1、……数字9的个数。整数间用一个空格分隔。10个数字的总个数不超过50,且至少拥有1个非0的数字。

输出格式:

在一行中输出能够组成的最小的数。

输入样例:
2 2 0 0 0 3 0 0 1 0
输出样例:
10015558

function f (arr) {
    let strWithoutZero = '';
    for (let i = 1; i < 10; i++) 
        strWithoutZero += new Array(arr[i] + 1).join(i.toString());
    
    let zeroStr = new Array(arr[0] + 1).join('0');

    let str = strWithoutZero[0] 
            + zeroStr 
            + strWithoutZero.substr(1, strWithoutZero.length - 1);

    return parseInt(str);
}

1026. 程序运行时间(15)

要获得一个C语言程序的运行时间,常用的方法是调用头文件time.h,其中提供了clock()函数,可以捕捉从程序开始运行到clock()被调用时所耗费的时间。这个时间单位是clock tick,即“时钟打点”。同时还有一个常数CLK_TCK,给出了机器时钟每秒所走的时钟打点数。于是为了获得一个函数f的运行时间,我们只要在调用f之前先调用clock(),获得一个时钟打点数C1;在f执行完成后再调用clock(),获得另一个时钟打点数C2;两次获得的时钟打点数之差(C2-C1)就是f运行所消耗的时钟打点数,再除以常数CLK_TCK,就得到了以秒为单位的运行时间。

这里不妨简单假设常数CLK_TCK为100。现给定被测函数前后两次获得的时钟打点数,请你给出被测函数运行的时间。

输入格式:

输入在一行中顺序给出2个整数C1和C1。注意两次获得的时钟打点数肯定不相同,即C1 < C2,并且取值在[0, 107]。

输出格式:

在一行中输出被测函数运行的时间。运行时间必须按照“hh:mm:ss”(即2位的“时:分:秒”)格式输出;不足1秒的时间四舍五入到秒。

输入样例:
123 4577973
输出样例:
12:42:59

const CLK_TCK = 100;

function f (c1, c2) {
    let seconds = (c2 - c1) / CLK_TCK;
    let h = Math.floor(seconds / 3600);
    let m = Math.floor((seconds - h * 3600) / 60);
    let s = (seconds - h * 3600 - m * 60).toFixed(0);
    return h + ':' + m + ':' + s;
}

1027. 打印沙漏(20)

本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印

*****
 ***
  *
 ***
*****

所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。

给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。

输入格式:

输入在一行给出1个正整数N(<=1000)和一个符号,中间以空格分隔。

输出格式:

首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。

输入样例:
19 *
输出样例:

*****
 ***
  *
 ***
*****
2
function f (n, ch) {
    let triangleHeight = 0;
    while (2 * triangleHeight * triangleHeight - 1 <= n)
        ++triangleHeight;
    --triangleHeight;

    let width = 2 * triangleHeight - 1,
        s = '';
    for (let chNum = width; chNum > 0; chNum -= 2) {
        let sideSpaceNum = (width - chNum) / 2;
        sideSpace = new Array(sideSpaceNum + 1).join(' ');

        centerCh = new Array(chNum + 1).join(ch);

        s += sideSpace + centerCh + sideSpace + '\n';
    }
    for (let chNum = 3; chNum <= width; chNum += 2) {
        let sideSpaceNum = (width - chNum) / 2;
        sideSpace = new Array(sideSpaceNum + 1).join(' ');

        centerCh = new Array(chNum + 1).join(ch);

        s += sideSpace + centerCh + sideSpace + '\n';
    }

    let spareChNum = n - (2 * triangleHeight * triangleHeight - 1);
    return s + spareChNum;
}

1042. 字符统计(20)

请编写程序,找出一段给定文字中出现最频繁的那个英文字母。

输入格式:

输入在一行中给出一个长度不超过1000的字符串。字符串由ASCII码表中任意可见字符及空格组成,至少包含1个英文字母,以回车结束(回车不算在内)。

输出格式:

在一行中输出出现频率最高的那个英文字母及其出现次数,其间以空格分隔。如果有并列,则输出按字母序最小的那个字母。统计时不区分大小写,输出小写字母。

输入样例:
This is a simple TEST. There ARE numbers and other symbols 1&2&3...........
输出样例:
e 7

function f (str) {
    var regExp = /[A-Za-z]/g;
    var arr = [];
    var result = regExp.exec(str);
    while (result) {
        arr.push(result[0].toLowerCase());
        result = regExp.exec(str);
    }
    arr.sort();

    var map = new Map();
    for (let ch of arr) {
        if (map.has(ch)) 
            map.set(ch, map.get(ch) + 1);
        else
            map.set(ch, 1);
    }

    var maxFreqCh = arr[0];
    for (let ch of arr) {
        if (map.get(ch) > map.get(maxFreqCh))
            maxFreqCh = ch;
    }

    return maxFreqCh + ' ' + map.get(maxFreqCh);
}
posted @ 2016-03-12 13:43  赵康  阅读(1254)  评论(0编辑  收藏  举报