目录
4. //6.11 已知不等式1! + 2! +... + m! < n, 请编程对用户指定的n值计算,并输出满足该不等式的m的整数解
8. 最大公约数GCD(greatest common divisor)
一、字符串
1.[编程题]字符串去特定字符
链接:https://www.nowcoder.com/questionTerminal/d5d0450134db4cb994a1b323a35262da
来源:牛客网
输入字符串s和字符c,要求去掉s中所有的c字符,并输出结果。
输入描述:
测试数据有多组,每组输入字符串s和字符c。
输出描述:
对于每组输入,输出去除c字符后的结果。
示例1
输入
heallo
a
输出
hello
测试用例:
nwlrbbmqbhcdarzowkkyhiddqscdxrjmowfrxsjybldbefsarcbynecdyggxxpklorellnmpapqfwkhopkmcoqhnwnkuewhsqmgb
b
答案:
1. 注意用getchar()吸收回车;
2. 开头的while是非法输入检测,
#include<stdio.h>
#include<string.h>
int main(){
char c,str[100];
while(scanf("%s",&str)!=EOF){ // 检测输入是否非法
getchar(); //吸收键入的回车符号
scanf("%c",&c); // 需要删除的字符
for(int i=0;i<strlen(str);i++){
if(str[i]==c) continue;
else printf("%c",str[i]);
}
printf("\n"); //输出字符串后换行
}
return 0;
}
2. 字符串链接
题目描述
不用strcat 函数,自己编写一个字符串链接函数MyStrcat(char dstStr[],charsrcStr[])
输入描述:
两个字符串,字符串由小写字母组成。
输出描述:
链接后的字符串
示例1
输入
复制
hello world
good morning
输出
复制
helloworld
goodmorning
答案1:数组版本
#include <stdio.h>
#include <stdlib.h>
# define N 80
void MyStrcat(char dstStr[], char srcStr[]);
int main()
{
char dstStr[N], srcStr[N];
scanf("%s %s", &dstStr, &srcStr);
// dstStr = "hello";
// srcStr = "world";
MyStrcat(dstStr, srcStr);
return 0;
}
void MyStrcat(char dstStr[], char srcStr[])
{
int i = 0;
int len1 = strlen(dstStr);
for(;srcStr[i] != '\0'; i++){
dstStr[len1 + i] = srcStr[i];
}
dstStr[len1 + i] = '\0';
printf("%s", dstStr);
}
答案2:指针版本
#include <stdio.h>
#include <stdlib.h>
# define N 80
char* MyStrcat(char* dstStr, char* srcStr);
int main()
{
char dstStr[N], srcStr[N];
scanf("%s %s", &dstStr, &srcStr);
// dstStr = "hello";
// srcStr = "world";
MyStrcat(dstStr, srcStr);
return 0;
}
char* MyStrcat(char* dstStr, char* srcStr)
{
char* pStr = dstStr; // 首地址
while(*dstStr != '\0') dstStr++;
while(*srcStr != '\0')
{
*dstStr = *srcStr;
dstStr++;
srcStr++;
}
*dstStr = '\0';
printf("%s", pStr);
return pStr;
}
3. 字符串内排序
题目描述
输入一个字符串,长度小于等于200,然后将输出按字符顺序升序排序后的字符串。
输入描述:
测试数据有多组,输入字符串。
输出描述:
对于每组输入,输出处理后的结果。
示例1
输入
复制
bacd
输出
复制
abcd
答案:冒牌排序
#include <stdio.h>
#include <stdlib.h>
# define N 200
void StrSort(char str[]);
int main()
{
char str[N];
scanf("%s", &str);
StrSort(str);
printf(str);
return 0;
}
void StrSort(char str[])
{
// bubble sort
int len = strlen(str);
char temp;
int i,j;
int flag;
for(i=0; i<len-1; i++){
flag = 0;
for(j=len-1; j>i; j--){
if(str[j] < str[j-1] ){ // 逆序对,交换
temp = str[j];
str[j] = str[j-1];
str[j-1] = temp;
flag = 1; // 该轮有交换
}
}
if(!flag)
return;
}
}
4. 实现Mystrcmp函数
首先通过指针对字符串进行比较,如“abcd”和“efddd”,比较第一个字母即刻得出大小;
对于字符串如“abcd”和“abc”,因为前三个字母a和b都相同,然后b就结束了,跳出循环。此时需要循环外的判断
int MyStrCmp(char a[], char b[])
{
int i;
for(i=0; a[i]!='\0' || b[i]!='\0'; i++)
{
if(a[i] > b[i]) return 1;
else if(a[i] < b[i]) return -1;
}
// 循环结束,某一指针指向'\0'
if(a[i] == b[i]) return 0;
else if(a[i] != '0') return 1;
else return -1;
}
二、其他
4. //6.11 已知不等式1! + 2! +... + m! < n, 请编程对用户指定的n值计算,并输出满足该不等式的m的整数解
答案
阶乘也有技巧, 不用创造一个Fact函数,每次在term的基础上*i即可
#include <stdio.h>
#include <stdlib.h>
int main()
{
unsigned long i, n, term =1 ,sum = 0;
scanf("%lu", &n);
for(i=1;; i++){
term *= i;
sum += term;
if(sum >= n )
break;
}
printf("the ans is %lu\n", i-1);
return 0;
}
5. 百鸡问题
校招时部分企业笔试将禁止编程题跳出页面,为提前适应,练习时请使用在线自测,而非本地IDE。
题目描述
用小于等于n元去买100只鸡,大鸡5元/只,小鸡3元/只,还有1/3元每只的一种小鸡,分别记为x只,y只,z只。编程求解x,y,z所有可能解。
输入描述:
测试数据有多组,输入n。
输出描述:
对于每组输入,请输出x,y,z所有可行解,按照x,y,z依次增大的顺序输出。
示例1
输入
复制
40
输出
复制
x=0,y=0,z=100
x=0,y=1,z=99
x=0,y=2,z=98
x=1,y=0,z=99
答案
为了省去x+y+z=100的约束关系,故对xyz进行穷举,而仅仅在x+y+z=100时进行输出,这样写代码更快
#include <stdio.h>
#include <stdlib.h>
int main()
{
// 穷举法
int x, y, z, n;
scanf("%d", &n);
for(x=0; x<=100; x++){
for(y=0; y<=100; y++){
for (z=0; z<=100; z++){
if((x+y+z==100) && 5*x+3*y+z/3.0<=n){
printf("x=%d,y=%d,z=%d\n", x, y, z);
}
}
}
}
return 0;
}
6. 百万富翁问题
题目描述
一个百万富翁遇到一个陌生人,陌生人找他谈了一个换钱的计划。该计划如下:我每天给你10 万元,你第一天给我1 分钱,第二天2 分钱,
第三天4 分钱……
这样交换 30 天后,百万富翁交出了多少钱?陌生人交出了多少钱?(注意一个是万元,一个是分)
输入描述:
该题没有输入
输出描述:
输出两个整数,分别代表百万富翁交出的钱和陌生人交出的钱,富翁交出的钱以万元作单位,陌生人交出的钱以分作单位。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int sum1=0, term=1, sum2=0,i=1;
while(i<=30)
{
sum1 += term;
term *=2;
i++;
}
sum2 = 10 * 30;
printf("%d %d", sum2, sum1);
return 0;
}
7. 最小公倍数
输入a和b,给出a和b的最小公倍数
输入: 5 10;输出10
输入:16,24; 输出:48
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a, b, ret, i;
scanf("%d %d", &a, &b);
for(i=1; i<=b; i++)
{
if(i*a % b == 0)
{
ret = i*a;
break;
}
}
printf("the ans is %d", ret);
return 0;
}
8. 最大公约数GCD(greatest common divisor)
对于给定的a和b,最大公约数gcd具有a%gcd=0 且 b%gcd=0;
法1:穷举法。得出a和b中较小者min,从min开始依次-1,判断a%min和b%min的余数是否为0,知道min=1;
法2:欧几里得法,也成辗转相除法。对a和b连续进行求余运算,知道余数为0。此时非0的除数即是最大公约数。
通过该性质:
例子如下:123456 和 7890 的最大公因数是 6,这可由下列步骤(其中,“a mod b”是指取 a ÷ b 的余数)看出:
a | b | a mod b |
123456 | 7890 | 5106 |
7890 | 5106 | 2784 |
5106 | 2784 | 2322 |
2784 | 2322 | 462 |
2322 | 462 | 12 |
462 | 12 | 6 |
12 | 6 | 0 |
法3:递归方法。通过如下性质:
答案1:穷举法
时空消耗:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a, b, min, gcd;
scanf("%d %d", &a, &b);
min = (a>b)? b : a;
while(min>=1)
{
if(a%min==0 && b%min==0)
{
gcd = min;
break;
}
min--;
}
printf("%d", gcd);
return 0;
}
答案2:辗转相除法
时空消耗:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a, b, max, min, temp;
scanf("%d %d", &a, &b);
if(a>b)
{
max = a;
min = b;
}
else
{
max = b;
min = a;
}
while(min!=0)
{
temp = min;
min = max % min;
max = temp;
}
printf("%d", max);
return 0;
}
答案3:递归法
时空消耗:
#include <stdio.h>
#include <stdlib.h>
int GcdRecurse(int a, int b);
int main()
{
int a, b, gcd;
scanf("%d %d", &a, &b);
gcd = GcdRecurse(a, b);
printf("%d", gcd);
return 0;
}
int GcdRecurse(int a, int b)
{
if(a==b) return a; // 递归终止条件
// 递归体
if(a > b) return GcdRecurse(a-b, b);
else return GcdRecurse(a, b-a);
}
9. 互换最大最小数
题目描述
输入一个数n,然后输入n个数值各不相同,调换数组中最大和最小的两个数,然后输出。
输入描述:
测试数据有多组,输入n(1<=n<=20),接着输入n个数。
输出描述:
对于每组输入,输出交换后的结果。
示例1
输入
复制
2
1 3
输出
复制
3 1
答案:
找到最大最小值对应的下标,并将二者交换
时空消耗:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n, i, maxIn=0, minIn=0, temp;
scanf("%d", &n);
int A[n];
for(i=0; i<n; i++)
{
scanf("%d", &A[i]);
}
for(i=0; i<n; i++)
{
if(A[i] > A[maxIn]) maxIn = i;
if(A[i] < A[minIn]) minIn = i;
}
temp = A[maxIn];
A[maxIn] = A[minIn];
A[minIn] = temp;
for(i=0; i<n; i++) printf("%d ", A[i]);
return 0;
}
10. 判断三角形类型
题目描述
给定三角形的三条边,a,b,c。判断该三角形类型。
输入描述:
测试数据有多组,每组输入三角形的三条边。
输出描述:
对于每组输入,输出直角三角形、锐角三角形、或是钝角三角形。
示例1
输入
复制
3 4 5
输出
复制
直角三角形
答案:
先把三角形的各条边提取max,mid,min。其中提取mid的方法比较特殊,是先计算sum,在计算max和min,接着根据mid = sum- max -min得出。否则通过比较的方法得到mid比较复杂。然后根据勾股定理判断三角形的类型
时空复杂度:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a, b, c, max, mid, min, sum, min2, mid2, max2;
scanf("%d %d %d", &a, &b, &c);
sum = a+b+c;
max = a>b?a:b;
max = max>c? max: c;
min = a<b? a: b;
min = min<c? min: c;
mid = sum - max - min;
min2 = min*min;
max2 = max*max;
mid2 = mid*mid;
if(max2 > mid2 + min2) printf("钝角三角形");
else if(max2 == mid2 + min2) printf("直角三角形");
else printf("锐角三角形");
return 0;
}
11. 找众数
题目描述
输入20个数,每个数都在1-10之间,求1-10中的众数(众数就是出现次数最多的数,如果存在一样多次数的众数,则输出权值较小的那一个)。
输入描述:
测试数据有多组,每组输入20个1-10之间的数。
输出描述:
对于每组输入,请输出1-10中的众数。
示例1
输入
复制
5 1 5 10 3 5 3 4 8 6 8 3 6 5 10 7 10 2 6 2
输出
复制
5
答案:
用桶排序的思路来解,A[]数组长度11, 标记着1-10的数字在数组中出现的次数。长度11是为了计算方便,如5出现,使A[5]++即可;若A[]数组长度为10,则为A[5-1]++;
时空复杂度:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int A[11]={0};
int i, n, mode=0;
for(i=0; i<20; i++)
{
scanf("%d", &n);
A[n]++;
}
for(i=0; i<10; i++)
{
if(A[i] > A[mode]) mode = i;
}
printf("%d", mode);
return 0;
}
12. 素数检测
输入一个数n,判断n是否是素数
方法:因子检测法
就是从2到n-1一个个的拿来尝试,看能否整除n,如果存在能够整数n的(找到一个因子),则n不是素数,否则认为n是素数。
优化1:实际,是不需要试探到n-1的,只要的n/2即可。因为若n=a*b,设a>=b, 必然有a>=2,所以b<=n/2
优化2:只要到n的二次方根即可,原因是:设n = a * b,且a、b均为n非平凡约数,显然a > n的二次方根和b > n的二次方根不可能同时成立,因为同时成立时 a * b就会大于n,所以如果n存在非平凡约数,至少有一个小于等于n的二次方根,因此遍历时i*i<=n即可
// 优化算法1
int IsPrime(int n)
{
int i, flag=1;
if(n==1) flag=0;
for(i=2; i*i<=n; i++) \\ 此方法比开方好
{
if(n%i==0)
{
flag = 0;
break;
}
}
if(flag == 1) printf("%d ", n);
}
13 回文数检测算法
输入n,判断n是否是回文数(1<=n <=1000)
回文数:回文数(或回文数)是指一个像14641这样“对称”的数,如1,11,121,。
思路1:开辟数组a[]存储n的各个位的值,然后再对a[]头尾2 方向遍历,判断其是否左右对称。
思路2(更好):设置一个变量inv,该数是变量n的逆数;若inv和n最终相等,则是回文数;
// 思路1
int IsHuiwen1(int n)
{
int a[4]={0};
int len=0, p1=0, p2=0, i=0; //数组实际长度,头尾指针
int num=n, flag=1; // 剩下的大小, flag
// 提取n的各个位数
while(num>0)
{
a[i] = num%10;
num = num/10;
i++;
}
len = i;
p2 = len-1;
// 对各个位数比较是否对称
for(; p1<p2; p1++,p2--)
{
if(a[p1] != a[p2])
{
flag = 0;
break;
}
}
return flag;
}
// 思路2
int IsHuiwen2(int n)
{
int num=n, inv=0;
while(num>0)
{
inv = inv * 10 + (num%10);
num = num / 10;
}
if(inv == n) return 1;
else return 0;
}
二. Hash应用
1. 统计同乘积学生人数
答案:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n, t;
while(scanf("%d", &n) != EOF && n!=0)
{
int Hash[101] = {0};
int i;
for(i=0; i<n; i++){
scanf("%d", &t);
Hash[t]++;
}
int x;
scanf("%d", &x);
printf("%d\n", Hash[x]);
}
return 0;
}
三、排版问题
1. 输出梯形
答案
观察图像特点,“ ”和“*”的频率和高度特点
#include <stdio.h>
#include <stdlib.h>
int main()
{
int h, maxLen, nStar, nSpace, i, j;
while(scanf("%d", &h) != EOF)
{
maxLen = h + (h-1) * 2;
for(i=0; i<h; i++)
{
nStar = h + i*2;
nSpace = maxLen - nStar;
for(j=0; j<nSpace; j++) printf(" ");
for(j=0; j<nStar; j++) printf("*");
printf("\n");
}
}
return 0;
}
2. 杨辉三角
输入h行数,输出入下图所示的杨辉三角:
组合公式:
答案:
为二项式的展开项的系数。
注意:想要输出占4位,使用printf("%4d");
#include <stdio.h>
#include <stdlib.h>
// 阶乘公式
int Fact(int n)
{
if(n <= 1) return 1;
int ret=1, i;
for(i=2; i<=n; i++) ret *= i;
return ret;
}
// 组合公式
int Com(int n, int m)
{
return (Fact(n)/(Fact(m)*Fact(n-m)));
}
int main()
{
int h, i, j;
while(scanf("%d", &h) != EOF)
{
for(i=0; i<h; i++)
{
for(j=0; j<=i; j++)
{
printf("%4d ", Com(i,j)); // 输出占4位,方便对齐
}
printf("\n"); // 换行
}
}
return 0;
}
输出: