算法入门笔记------------Day2

1.开灯问题

有n盏灯,编号为1~n,第一个人把所有灯打开,第二个按下所有编号为2的倍数的开关(这些灯都被关掉),第三个人按下所有编号为3的倍数的开关,依次类推,一共有k个人,问最后有哪些灯开着?输入n和k,输出开着的灯的编号?

#include<stdio.h>
#include<string.h>
int a[1000]; //我们用数组来保存灯的状态
int main(void)
{
        int n,k,i,j;
        int first=1;//最后的格式输出
        memset(a,0,sizeof(a));  //把灯先设置为0,表示灯是关的
        //然后模拟所有的关灯和开灯的操作
        scanf("%d%d",&n,&k);  //输入人数和灯数
        for(i=1;i<=k;i++)
        {
            for(j=1;j<=n;j++)
            {
                    if(j%i==0)     a[j]=!a[j];   //如果满足条件,按动开关
            }
        }
        for(j=1;j<=n;j++)
        {
                if(a[j]==1)
                {
                        if(first)    first=0;
                        else    printf(" ");
                        printf("%d",j);
                }
        }
        printf("\n");
        return 0;
}

2.蛇形填数

在n*n的方阵填入1,2,...,n*n,要求填成蛇形,例如n=4

10  11 12 1

9   16 13  2

8   15 14  3

7   6   5     4

#include<stdio.h>
#include<string.h>
#define MAX 10
int a[MAX][MAX];
int main(void)
{
        int x,y,n,tot;
        scanf("%d",&n);         `
        memset(a,0,sizeof(a));
        tot=a[x=0][y=n-1]=1;    //确定起点
        while(tot<n*n)       //判断有没有越界,注意下一个是不是0,还有如果x+1<n为假,则就不计算后面的,因为&&短路预算
        {
            while(x+1<n && !a[x+1][y])      a[++x][y]=++tot;
            while(y-1>=0 && !a[x][y-1])       a[x][--y]=++tot;
            while(x-1>=0 && !a[x-1][y])       a[--x][y]=++tot;
            while(y+1<n && !a[x][y+1])        a[x][++y]=++tot;
        }
        for(x=0;x<n;x++)
        {
            for(y=0;y<n;y++)
                printf("%3d",a[x][y]);
            printf("\n");
        }
        return 0;
}

3.竖式问题

 找出所有形如abc*de的算式,使得在完整的竖式中,所有数字都属于一个特定的数字集合,输入数字集合,输出所有竖式.

#include<stdio.h>
#include<string.h>
int main(void)
{
        char s[20],buf[100];
        int abc,de,x,y,z,ok;
        int num=0;
        scanf("%s",s);
        for(abc=111;abc<=999;abc++)
        {
            for(de=11;de<=99;de++)
            {
                    x=abc*(de%10);y=abc*(de/10);z=abc*de;
                    sprintf(buf,"%d%d%d%d%d",abc,de,x,y,z);     //写入字符串buf中
                    ok=1;
                    for(int i=0;i<strlen(buf);i++)                  //比较buf和s中的字符是不是都有
                    {
                            if(strchr(s,buf[i])==NULL)      ok=0;
                    }
                    if(ok)                  //成功的标志
                    {
                            printf("<%d>\n",++num);         //计数
                            printf("%5d\nX%4d\n-----\n%5d\n%4d\n-----\n%5d\n\n",abc,de,x,y,z);
                    }
            }
        }
        printf("The number of solutions =%d\n",num);
        return 0;
}

4.最长回文子串

输入一个字符串,求出其中最长的回文子串.

//分析,首先不适用使用scanf来输入字符串,因为碰到空格或者TAB就会停下
//于是我们可以使用fgets
//先找最大回文子串的长度
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#define MAX 5000
char buf[MAX],s[MAX];
int main(void)
{
        int n,m=0,max=0;
        int i,j,k;
        fgets(buf,sizeof(buf),stdin);       //输入字符串
        n=strlen(buf);          //求字符串长度
        for(i=0;i<n;i++)
            if(isalpha(buf[i]))    s[m++]=toupper(buf[i]);      //全部变成大写,方便判别
        for(i=0;i<n;i++)
        {
            for(j=0;j<m;j++)
            {
                    int ok=1;
                    for(k=i;k<=j;k++)                       //s[k]的对称位置是s[i+j-k]
                    {
                            if(s[k]!=s[i+j-k])   ok=0;
                    }
                    if(ok&&j-i+1>max)  max=j-i+1;
            }
        }
        printf("max=%d\n",max);
        return 0;
} 

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#define MAX 5000
char buf[MAX],s[MAX];
int p[MAX];
int main(void)
{
        int n,m=0,max=0;
        int x,y,i,j;
        fgets(buf,sizeof(buf),stdin);
        n=strlen(buf);
        for(i=0;i<n;i++)
        {
            if(isalpha(buf[i]))
            {
                p[m]=i;
                s[m++]=toupper(buf[i]);
            }
        }
        for(i=0;i<m;i++)
        {
            for(j=0;i-j>=0&&i+j<m;j++)              //从内部向外分开,奇数情况,aba
                {
                    if(s[i-j]!=s[i+j])      break;
                    if(j*2+1>max)      {
                        max=j*2+1;
                        x=p[i-j];
                        y=p[i+j];
                    }
                }
            for(j=0;i-j>=0&&i+j+1<m;i++)        //从内部向外分开,偶数情况,考虑aabb
            {
                if(s[i-j]!=s[i+j+1])        break;
                if(j*2+2>max)       {
                        max=j*2+2;
                        x=p[i-j];
                        y=p[i+j+1];
                }
            }
        }
        for(i=x;i<=y;i++)
            printf("%c",buf[i]);
        printf("\n");
        return 0;
}

习题

分数统计

任务1 分数为不吵为100的非负整数

#include<stdio.h>
#include<string.h>
int main(void)
{
        int num[110];
        int x;
        int ans;
        int max=0;
        memset(num,0,sizeof(num));
        while(scanf("%d",&x)==1)
        {
                num[x]++;
        }
        for(int i=0;i<=100;i++)
        {
                if(num[i]>=max)
                {
                     max=num[i];
                     ans=i;
                }
        }
        for(int i=0;i<101;i++)
        {
                if(num[i]==max)
                    printf("%d ",i);
        }
        printf("\n");
        return 0;
}

  任务2 输入为不超过100的非负实数

//习题3.1,分数统计(stat)
#define LOCAL
#include<stdio.h>
#include<string.h>
#include<math.h>
#ifndef MAX
#define MAX 10000+1
#endif
int a[MAX];
int main(){
    //从本地读取文件(重定向),不用每次都进行数据输入
    #ifdef LOCAL
    freopen("data.txt","r",stdin);
    #endif
    memset(a,0,sizeof(a));
    double degree;
    while(scanf("%lf",&degree) == 1){
        //直接double强制转化为int会出现问题,如4.9999999999,应为5,但会是4.9
        //使用floor进行四舍五入可以解决这个问题
        double m = degree * 100;
        int n = floor(m+0.5);
        a[n] += 1;
    }

    int i,max = a[0];
    int tmp[MAX];
    memset(tmp,0,sizeof(tmp));
    for(i=1; i <= MAX; i++){
        if(a[i] > max){
            max = a[i];
        }
    }
    int j = 0;
    for(i = 0; i < MAX; i++){
        if(a[i] == max){
            tmp[j] = i;
            j++;
        }
    }
    for (i = 0; i < j; ++i)
    {
        double temp = tmp[i]*0.01;
        printf("%.2f\n",temp);
    }
    return 0;
}

单词的平均长度

#include<stdio.h>
int main(void)
{
        char ch;
        int num=0,words=0;
        int inword=0;
        while((ch=getchar())!=EOF)
        {
                if(isalpha(ch))    num++;
                if(!isspace(ch)&&!inword)
                {
                        inword=1;
                        words++;
                }
                if(isspace(ch)&&inword)
                        inword=0;
        }
        printf("The averge word is %.2f\n",(double)num/words);
        return 0;
}

乘积的末3位

输入若干个整数(可以是正数、负数或者零),输出它们的乘积的末3位。这些整数中会混入一些由大写字母组成的字符串,你的程序应该忽略它们。提示:试试看,在执行scanf("%d")时输入一个字符串会怎样?

输入:AB123CC   BB123123321321          DDD22    888888888888888888888888888ZZ      -411B

输出:968

输入:AA-11BBB   D2CCC

输出:-22

假定末3位是指,不足3位就输出数字本身,如果是负数则包括负号,比如结果是-12,则输出-12;结果是11,则输出11,结果是0,则输出0;

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define N 100000
#define M 5000
#define L 5
char input[N];
char str[M];
char tmp[L];
char rev[L];

int main(void)
{
	int i, len, k;
	int flag = 1;
	int product = 1;
	char *p = NULL;

	fgets(input, sizeof (input), stdin);
	p = input;
	while (sscanf(p, "%s", str) == 1) {
		len = k = 0;
		for (i = strlen(str)-1; i != -1; i--) {
			if (len != 3 && 1 == isdigit(str[i]))
				tmp[len++] = str[i];
			if (str[i] == ‘-‘) {
				flag = -flag;
				break;
			}
		}
		tmp[len] = ‘\0‘;
		while (len > 0)
			rev[k++] = tmp[--len];
		rev[k] = ‘\0‘;
		product *= atoi(rev);
		product %= 1000;
		p += strlen(str)+1;
		while (*p == ‘ ‘) p++;/* 滤空 */
	}
	printf("%d\n", product < 100 ? product*flag : product);
	return 0;
}

计算器 

编程程序读入一行恰好包括一个+或-或*的表达式,输出它的值。运算符保证是二元运算符,且两个运算数均不超过100的非负整数。运算数和运算符可以紧挨也可以有一个或多个空格、TAB隔开。行首尾均可以有空格。提示:选择合适的输入方法可以将问题简化。

#include <stdio.h>
#define N 1000
char str[N];
int main(void)
{
	char *p = NULL;
	int op1, op2;

	fgets(str, sizeof(str), stdin);//it will contains ‘\n‘;

	for (p = str; *p != ‘\n‘; p++) {
		if (*p == ‘+‘ || *p == ‘-‘ || *p == ‘*‘)
			break;
	}
	if (*p != ‘\n‘){
		switch(*p) {
		case ‘+‘:
			sscanf(str, "%d + %d", &op1, &op2);
			printf("%d\n", op1+op2);
			break;
		case ‘-‘:
			sscanf(str, "%d - %d", &op1, &op2);
			printf("%d\n", op1-op2);
			break;
		case ‘*‘:
			sscanf(str, "%d * %d", &op1, &op2);
			printf("%d\n", op1*op2);
			break;
		}
	}
	return 0;
}

 输入一个n*n字符矩阵,把它左旋90度后输出

#include <stdio.h>
#define N 100

char a[N][N];
int main(void)
{
	int n;
	int i, j;

	scanf("%d", &n);

	for (i = 0; i != n; i++) {
		for (j = 0; j != n; j++)
			scanf("%s", &a[i][j]);
	}

	for (j = n-1; j != -1; j--) {
		for (i = 0; i != n; i++)
			printf("%c ", a[i][j]);
		printf("\n");
	}

	return 0;
}

  进制转换

#include <stdio.h>
voidtrans(int n, int b)
{
	if (n >= b)
		trans(n/b, b);
	printf("%d", n%b);
}
void trans(int n, int b);
int main(void)
{
	int b, n;

	scanf("%d %d", &b, &n);
	trans(n, b);
	printf("\n");
	return 0;
}

//非递归
#include <stdio.h>
#define N 100
int a[N];
int main(void)
{
	int b, n;
	int k = 0;
	int i;

	scanf("%d %d", &b, &n);
	while (n >= b) {
		a[k++] = n%b;
		n /= b;
	}
	a[k++] = n%b;
	for (i = k-1; i != -1; i--)
		printf("%d", a[i]);
	printf("\n");
	return 0;
}

//输出基数b( 2 <= b <= 10)和正整数n(b进制),输出n的十进制表示
#include <stdio.h>
#include <string.h>
#define N 100
char str[N];
int main(void)
{
	int n, i, k, tmp;
	int res = 0;

	scanf("%d %s", &n, str);
	for (i = strlen(str)-1; i != -1; i--) {
		tmp = str[i]-‘0‘;
		k = strlen(str)-1-i;
		while(k--)
			 tmp *= n;
		res += tmp;
	}
	printf("%d\n", res);

	return 0;
}

  

时间: 2024-12-27 20:16:14

算法入门笔记------------Day2的相关文章

算法入门笔记------------Day1

1.C语言使用%d显示float值,不会把float值转换为近似的int值,而是显示垃圾值,使用%f显示int值,也不会把该int值转换为浮点值 2.三位数反转:输入一个三位数,分离它的百位,十位和个位,反转后输出 #include<stdio.h> int main(void) { int a; scanf("%d",&a); printf("%d %d %d\n",a%10,a/10%10,a/100); return 0; } //考虑25

算法入门笔记------------Day3

主要是复习前面的基本内容,以及函数的概念 组合数 #include<stdio.h> int f(int n) { int m=1; for(int i=1;i<=n;i++) m*=i; return m; } int main(void) { int n,m; scanf("%d%d",&n,&m); printf("%d\n",f(n)/(f(m)*f(n-m))); return 0; } 孪生素数 #include<

由LCS到编辑距离—动态规划入门—算法学习笔记

一切计算机问题,解决方法可以归结为两类:分治和封装.分治是减层,封装是加层. 动态规划问题同样可以用这种思路,分治. 它可以划分为多个子问题解决,那这样是不是用简单的递归就完成了?也许是的,但是这样会涉及太多的不便的操作.因为子问题有重叠! 针对这种子问题有重叠的情况的解决,就是提高效率的关键. 所以动态规划问题可以总结为:最优子结构和重叠子问题. 解决这个子问题的方式的关键就是:memoization,备忘录. 动态规划算法分以下4个步骤: 描述最优解的结构 递归定义最优解的值 按自底向上的方

redis入门笔记(1)

redis入门笔记(1) 1. Redis 简介 •Redis是一款开源的.高性能的键-值存储(key-value store).它常被称作是一款数据结构服务器(data structure server).Redis的键值可以包括字符串(strings)类型,同时它还包括哈希(hashes).列表(lists).集合(sets)和 有序集合(sorted sets)等数据类型. 对于这些数据类型,你可以执行原子操作.例如:对字符串进行附加操作(append):递增哈希中的值:向列表中增加元素:

MySQL入门笔记(一)

MySQL入门笔记(二) 一.数据类型 1. 整型 2. 浮点型 3. 字符型 4. 日期时间型 二.数据库操作 1. 创建库 CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name [DEFAULT] CHARACTER SET [=] charset_name; ??上述代码中DATABASE和SCHEMA完全相同,可任选一个(花括号内的参数为任选其一): ??添加IF NOT EXISTS的作用则是,若新建数据库的名称与已有数据库名称冲突,则产

Django入门笔记【一】

入门笔记翻译整理自:https://docs.djangoproject.com/en/1.8/ *该笔记将使用一个关于投票网络应用(poll application)的例子来阐述Django的用法. 1. 查看Django是否安装及版本 1 $ python -c "import django; print(django.get_version())" 2. 创建一个项目(project) 通过cd方式进入自创目录,然后运行: 1 $ django-admin startprojec

算法系列笔记5(扩展数据结构-动态顺序统计和区间树)

在编程中,我们往往使用已有的数据结构无法解决问题,这是不必要急着创建新的数据结构,而是在已有数据结构的基础上添加新的字段.本节在上一次笔记红黑树这一基础数据结构上进行扩展,得出两个重要的应用-动态顺序统计和区间树. 动态顺序统计 在算法系列笔记2中我们在线性时间内完成了静态表的顺序统计,而这里我们在红黑树上进行扩展,在O(lgn)时间内完成该操作,主要包括返回第i 排名的元素os_select(i)和给定一个元素x,返回其排名(os_rank(x)). 思想:添加新项:在红黑树的结点上记录下该结

MIT算法导论笔记

详细MIT算法导论笔记 (网络链接) 第一讲:课程简介及算法分析 第二讲:渐近符号.递归及解法

嵌入式OS入门笔记-以RTX为案例:十.Keil的RTX调试支持

嵌入式OS入门笔记-以RTX为案例:十.Keil的RTX调试支持 调试(debug)是软件开发的一个重要环节,对于嵌入式开发而言这个环节其实比较依赖一些硬件资源(硬件debugger)的支持.传统的嵌入式系统的调试比较依赖断点(breakpoint)和单步调试(single step through).而 ARM cortex-M 系列的芯片其实有很强的CoreSight片上调试支持,实际上就是一个小的调试硬件,作为ARM的标准,内嵌在ARM的芯片里.在ARM自家的调试器ULINK-pro等的帮