C 的学习第五天

今天写了一天的关于数组和算法排序的问题,做编程这两年,真真正正的在今天发现了算法的美妙之处,

怪不得大家说C的程序简洁.那学习了指针之后,直接操作地址的话,我们能实现的东西岂不是更多了,

这可比C上得调用来的舒服多,有一种掌握自己的思想的感觉.

首先是一道让我想了3小时没头绪的问题.

有1000000个数,每个数取值范围是0-999999

找出其中重复的数。

拿到这道题,我首先想得是分类,a[i]%10..%100...%1000 ,发现不行,因为有两个极端情况,一, 

这一百万全部是一个数字;二,这一百万全不同;这两种情况就把分堆处理变成一个笑话.

其次我开始思考拿另外一个数组计数,就是这个数出现一次在另一个数组中加一,这和正确答案很接近了

可是最后一步没走通,怎么记录这个数的值,再让它和次数关联.

当最后,我实在没有办法,在网上看算法的博客时突然看见了计数排序这个方法,突然想到来用这道题再好不过了.

for(int i = 0 ; i < 1000 ; i ++){
        a[i] = arc4random()%1000;
        b[a[i]]++;
    }
    for (int j = 0 ; j < 1000; j++) {
        if(b[j] > 1){
            count++;
            printf("重复数是%d ",j);
        }
    }
这个理念就是a[i] 中的数 是b[a[i]]的下标.

体会到算法的美妙了啊


2、找出一个二维数组中的“鞍点”,即该位置上的元素在该行中最大,在该列中最小(也可能没鞍点),打印出有关信息。

void homework6()
{
    /*
     3、找出一个二维数组中的“鞍点”,即该位置上的元素在该行中最大,
     在该列中最小(也可能没鞍点),打印出有关信息。
     */
    int a[3][4] = {{1,2,5,4},{2,3,5,9},{10,13,9,21}};
    
    int b [9] = {0}, c[9] = {0}, d[10] = {0} , max = 0, t = 0;
    for (int i = 0; i < 3; i ++) {
        max = a[i][0];
        //保证每次循环时初始化n
        int n = 0;
        for (int j = 0 ; j < 4; j ++) {
            if(max < a[i][j]){
                max = a[i][j];
                n = j ;
            }
        }
        //第几行几列和实际数组中大1 所以加1
        //数组里存储数据的方式是 b 行数 c 列数 d 实数 循环存储.
        b[i] = i;
        c[i] = n;
        d[i] = a[i][n];
    }
  
    for (int k = 0 ; k < 3; k ++) {
        int min = d[k],n = 0;
        for(int j = 0 ; j < 4 ; j ++ ){
            if(min > a[j][c[k]]){
                min = a[j][c[k]];
                n = j ;
            }
        }
        if(d[k] == min){
            printf("马鞍数是%d 第%d行第%d列",min,n+1,c[k]+1);
        }else{
            t++;
        }
    }
    if (t == 3) {
        printf("无马鞍数");
    }  
}

这道题用的是分开思考的方法 先找每行最大,再找这个最大数的列的最小.

马鞍数在一个数列只有一个



3、耶稣有13个门徒,其中有一个就是出卖耶稣的叛徒,请用排除法找出这位叛徒:

13人围坐一圈,从第一个开始报号:1,2,3,1,2,3...。凡是报到“3”就退出圈子,

最后留在圈子内的人就是出卖耶稣的叛徒。请找出它原来的序号。


这也是一个经典问题了,感觉自己对这种循环的问题不在强项 下面是代码

void jesus()
{
        /*
         3、耶稣有13个门徒,其中有一个就是出卖耶稣的叛徒,请用排除法找出这位叛徒:13人围坐一圈,从第一个开始报号:1,2,3,1,2,3...。凡是报到“3”就退出圈子,最后留在圈子内的人就是出卖耶稣的叛徒。请找出它原来的序号。
         */
        //思路解析: 找一个a[13]的数组,所有位为0,开始以n = 3 报数 到3变1
        
    int a[13] = {0};
    int n = 1 , p = 0;
    for(int i = 0 ; i < 14; i ++){
        // i 表示人数(0-12) 13 取不到的
        if(i == 13){
            i = -1;
            continue;
        }
        //n是报数
        if(n == 3){
            if(a[i] == 0){
                a[i] = 1;
                n = 0;
                p++;
            }else{
                n = 2 ;
            }
        }
        //p是点到名的人数
        if(p == 12){
            break;
        }
        n++;
    }
    for (int j = 0 ; j < 13; j ++) {
        if(a[j] == 0 ){
            printf("%d",j+1);
        }
    }  
}


这道题的重点在于循环 和 状态 循环我是用i==13 后 重新赋值完成的 状态的话是用另外一个数组做指示器.

其他的都是一些练习吧,慢慢的改变自己的编程习惯,尽量使自己的代码简洁高效,让循环和判断这些能更好的合作


坚信一句话: 你今天所承受的困难,都是你以后吹牛的资本!



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值