有意思的题目01

数组去重

题目:手动输入一个数组(int),长度自定,将数组内容去重,并输出值

输入:1 2 3 2 4 2 5 2 6 2

输出:1 3 4 5 6

 思路:

1.先找到重复数字,能够两两对比的方法,可以进行选择排序
2.将重复数字改为标记数字,这里为了方便我选的是0

        当然,为了避免与数组中值重复,导致出错,可以用 stdlib 头文件下面的 rand()函数获取一个随机值,将其与数组内容对比,没有相等的就作为标记值

3.将标记数组后移

//创建测试数组,后续可以添加scanf来手动输入数组
//测试数组1
//int nums[10] = {1,2,3,2,4,2,5,2,6,2};
//测试数组2
int nums[10] = {1,1,1,1,1,1,1,1,1,1};

//值交换容器
int p;
//标记值计数器
int count = 0;
//两层循环进行选择排序,这里是从尾端开始的
for (int i = 9; i >= 0; --i) {
    for (int j = 0; j < i; ++j) {

        //外层循环选择的数与内层循环选择的数相等时,改成标记数字
        if(nums[i] == nums[j]){
            nums[i] = 0;
            //优化算法用的,记录有几个标记值
            count++;
        }

        //因为是反向遍历,所以需要把标记数字后移到尾部
        //不加count也能得出答案,但是遍历的次数增加了
        // 因为每执行一次上一层循环,就将标记值打到了数组后方,只需要遍历除了标记值的地方就行
        for (int k = i; k < 10 - count; ++k) {
            //判断当前位置是不是标记值,是标记值就后移
            if(nums[k] == 0) {
                p = nums[k];
                nums[k] = nums[k + 1];
                nums[k + 1] = p;
            }
        }
    }
}

//打印输出标记值之前的数字
for (int i = 0; i < 10 - count; ++i) {
    printf("%d ",nums[i]);
}

查找考生信息

每个 PAT 考生在参加考试时都会被分配两个座位号,一个是试机座位,一个是考试座位。正常情况下,考生在入场时先得到试机座位号码,入座进入试机状态后,系统会显示该考生的考试座位号码,考试时考生需要换到考试座位就座。但有些考生迟到了,试机已经结束,他们只能拿着领到的试机座位号码求助于你,从后台查出他们的考试座位号码。

输入格式:

输入第一行给出一个正整数 N(≤1000),随后 N 行,每行给出一个考生的信息:准考证号 试机座位号 考试座位号。其中准考证号由 16 位数字组成,座位从 1 到 N 编号。输入保证每个人的准考证号都不同,并且任何时候都不会把两个人分配到同一个座位上。

考生信息之后,给出一个正整数 M(≤N),随后一行中给出 M 个待查询的试机座位号码,以空格分隔。

输出格式:

对应每个需要查询的试机座位号码,在一行中输出对应考生的准考证号和考试座位号码,中间用 1 个空格分隔。

输入样例:

4
3310120150912233 2 4
3310120150912119 4 1
3310120150912126 1 3
3310120150912002 3 2
2
3 4

输出样例:

3310120150912002 2
3310120150912119 1 

思路:

考生信息是一个结构体,只需将其创建一个链表串联起来即可,用基本的链表的创建销毁,增删改查,即可的到信息,没有涉及太多的算法 

#include
#include
#include 
//创建结构体,a:准考证号,sjh:上机号,zwh:座位号,next:结构体指针
typedef struct Note{
    char a[20];
    int sjh;
    int zwh;
    struct Note* next;
}Note;

//创建新节点
void Note_new_head(Note *note , char *a, int sjh, int zwh);
//找到节点并输出
void find_out_info(Note *note, int sjh);
int main(){
    //创建考生信息结构体的头节点,将其指向空
    Note note;
    note.next = NULL;
    //创建结构体的基本数据容器,包括准考证号,试机座位号,考试座位号
    char a[20];
    int sjh,zwh;
    //记录考生信息的条数
    int N;
    scanf("%d",&N);

    //循环记录考生的信息
    for(int i = 0;i < N ;++i){
        //键盘记录考生信息
        scanf("%s %d %d",a,&sjh,&zwh);
        //调用头插法,插入信息链表
        Note_new_head(¬e,a,sjh,zwh);
    }

    //创建查询数量容器,通过键盘键入
    int num;
    scanf("%d",&num);

    //创建记录上机号容器
    int find_sjh;
    //循环记录值,并调用找寻输出函数
    for(int i = 0; i < num;++i){
        scanf("%d",&find_sjh);
        //调用找寻输出函数
        find_out_info(¬e,find_sjh);
    }

    return 0;
}

//创建新节点,并使用头插法插入链表
void Note_new_head(Note *note , char *a, int sjh, int zwh){
    //创建新节点,并分配空间
    Note* new_note = (Note *)malloc(sizeof(Note));
    //赋值
    strcpy(new_note->a,a);
    new_note->sjh = sjh;
    new_note->zwh = zwh;
    //头插
    new_note->next = note->next;
    note->next = new_note;
}
//创建查询输出函数
void find_out_info(Note *note, int sjh){
    //创建指针指向头节点
    Note* p = note->next;
    //遍历链表,找到符合的上机号,并输出其准考证号和座位号
    while(p != NULL){
        if(p->sjh == sjh){
            printf("%s %d\n",p->a,p->zwh);
            return;
        }
        p = p->next;
    }
}

6-10 阶乘计算升级版

本题要求实现一个打印非负整数阶乘的函数。

函数接口定义:

void Print_Factorial ( const int N );

其中N是用户传入的参数,其值不超过1000。如果N是非负整数,则该函数必须在一行中打印出N!的值,否则打印“Invalid input”。

裁判测试程序样例:

#include  

void Print_Factorial ( const int N ); 

int main() {

    int N; scanf("%d", &N);
    Print_Factorial(N); 
    return 0; 
} 

/* 你的代码将被嵌在这里 */

输入样例:

15

输出样例:

1307674368000 

思路:我第一此写的时候,只是简单的使用for循环解决,计算结果,最开始时使用的int的数据类型接受结果,最后测试结果发现只有部分正确,提示上面写的计算1000的阶乘时错误了,我就开始思考了

void Print_Factorial ( const int N ){
    //处理特殊情况:<0 >1000
    if(N < 0 || N > 1000){
        printf("Invalid input");
        return;
    }

    //创建阶乘容器
    unsigned long long factorial = 1;
    for(unsigned long long i = 1;i <= N;++i){
        factorial *= i;
    }
    printf("%lld\n",factorial);
    //结果:unsigned long long的范围不足以储存1000的阶乘
}

有意思的题目01_第1张图片

所以我改变思路,从数组出发,简单的进位计算就解决了

数组的每一个位置值储存结果的每一位值,每一个值都需要去与阶乘的下一个数进行乘法计算,计算完的结果的个位数就是这个位置的值,也就是%10即可的得到答案,然后将结果除个10,就是需要进位的数,将除10后的值与下一位值和阶乘的下一个数乘法计算后的结果相加再%10就是下一位的值,如此往复,就是答案 

我的代码的注释写的很详细,可以看看,就知道了

void Print_Factorial(const int N){
    //处理特殊情况
    if(N > 1000 || N < 0){
        printf("Invalid input");
        return;
    }
    
    //定义数组容器
    int factorial_arr[3000] = {0};
    //特殊情况隔离,1和0的阶乘为1;
    factorial_arr[0] = 1;
    //设置基础长度为1
    int length = 1;
    //设置位相乘容器
    int produnt;
    //设置相乘进位容器
    int carry_product;
    
    //阶乘
    for(int i = 2;i <= N;++i){
        
        //第一遍初始化进位容器,之后每次循环都重置进位容器
        carry_product = 0;
        
        //将length长度范围内的所有位相乘取余
        for(int j = 0;j < length;++j){
            
            //第一遍注入个位相乘结果给product
            //之后把相乘后需要进位的carcarry_product加上注入
            produnt = factorial_arr[j] * i + carry_product;
            
            //将位相乘的结果取余注入当前遍历到的位
            factorial_arr[j] = produnt % 10;
            
            //记录相乘后的进位值
            carry_product = produnt / 10;
        }

        //当前的carcarry_product是超过length长度的进位值
        while(carry_product){
            //将进位值按照长度依次注入阶乘容器
            factorial_arr[length] = carry_product % 10;
            carry_product /= 10;
            //将长度增加
            length++;
        }
    }

    //打印数组值
    for(int i = length - 1;i >= 0;--i){
        printf("%d",factorial_arr[i]);
    }
    printf("\n");
}

 

你可能感兴趣的:(算法,c语言,学习,排序算法,数据结构)