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);
}