C 解决百度知道的一个高中题

前言

  今天看见一道百度知道上提问,是这样的.

仔细算了一下, 花了 30min. 才整出来了, 估计现在回去参加高考, 数学及格都悬. 有时候想做这样的题有什么用,

学这些东西有什么意义, 在这种方面浪费时间有什么值得的.

后来想出来,

    开心就好!

想太多, 考虑太多心累. 我们开心就好.

 

正文

第一部分 从验证代码说开来

采用的主要思路是穷举法, 穷举完之后, 再判断. 思考了一下, 主要用 char str[5]; 保存这个这个串. 采用下面函数检测这个串

是否是想要的串

// aa 串检测函数
static bool isaa(const char str[], int len) {
    int i = 0;
    while(++i < len) {
        if (str[i] == 'a' && str[i-1] == 'a') {
            return true;
        } 
    }
    return false;
}

那怎么构建这个 char str[5] 呢. 这里原本采用 5 层 for, 这直接 pass 了, 首先一条准则, C 程序开发一定要记住, 或者程序员也要记住

1 /*
2   用不用 goto 取决你的业务复杂度
4  */
5 
6 // 但是你一定不要用 超过三层的 循环, 那种代码写出来后要打自己脸.

.后面采用 递归搞了一下, 如下

// 递归穷举
static void dgaa(char str[], int len, int idx, int * psum, int * pcut) {
    if (idx < len) {
        str[idx] = 'a';
        dgaa(str, len, idx + 1, psum, pcut);

        str[idx] = 'b';
        dgaa(str, len, idx + 1, psum, pcut);

        str[idx] = 'c';
        dgaa(str, len, idx + 1, psum, pcut);

        return;
    }
    // idx >= len 时候会进入下面计算流程
    ++*psum;
    *pcut += isaa(str, len);
}

最后需要 return,因为到这里就结束了,不能再往下了,否则重复计数了. 大家有好方法可以分享.

到这里一切都准备妥当了. 完整代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

// aa 串检测函数
static bool isaa(const char str[], int len) {
    int i = 0;
    while(++i < len) {
        if (str[i] == 'a' && str[i-1] == 'a') {
            return true;
        } 
    }
    return false;
}

// 递归穷举
static void dgaa(char str[], int len, int idx, int * psum, int * pcut) {
    if (idx < len) {
        str[idx] = 'a';
        dgaa(str, len, idx + 1, psum, pcut);

        str[idx] = 'b';
        dgaa(str, len, idx + 1, psum, pcut);

        str[idx] = 'c';
        dgaa(str, len, idx + 1, psum, pcut);

        return;
    }
    // idx >= len 时候会进入下面计算流程
    ++*psum;
    *pcut += isaa(str, len);
}

/*
 * 这里处理一个问题
 *  一个由 abc 组成的五位字符串, 至少包含 一个连续 aa 的串有多少个.
 * 
 * gcc -g -Wall -Wextra -O2 -o aa aa.c && ./aa
 */
int main(void)
{
    int sum = 0, cut = 0;
    char str[5];
    dgaa(str, sizeof(str)/sizeof(*str), 0, &sum, &cut);

    printf("所要找的所有串: %d 个, 至少出现一次 aa 的串有 %d 个!\n", sum, cut);

    return 0;
}

直接编译链接后跑一下

gcc -g -Wall -Wextra -O2 -o aa aa.c && ./aa

答案是 至少出现一次 aa 的串有 79 个.

 

第二部分 从高中数学角度分析这个问题

  采用思路是简单的数学集合分析.

1) . abc 组成 长度为 5 的串

    一共有 3^5 = 81 x 3 = 243

2) . 没有出现过 aa 连续的串个数

  A) 串中没有 a

    2^5 = 32

  B) 串中只有一个 a

    首先剩下 4 个位置 2^4 = 16 后面 一个 a 插入 到    x | x | x | x | x 

    x 的位置 有 C(1,5) = 5 种插入情况, 一共有 16 x 5 = 80 种

  C) 串中有两个 a  x | x | x | x 左边 x 的位置选出 2 个 插入 aa

    一共有 2^3 x C(4,2) = 8 x 4 x 3 / 2 = 48 种

  D) 串中有 3 个 a  就是这样情况 a | a | a

    只有 2^2 = 4 四种情况

  综上 A,B,C,D 一共有 32 + 80 + 48 + 4 = 112 + 52 = 164 种

综上1) 2) 得到至少一个 aa 连续出现的 5 位串 个数为

  243 - 164 = 79 种

问题已经解决. 欢迎大家给出更巧妙的方法分享.

 

后记

   到这里说结束了, 错误是难免的,提出来一定改. 祝今天大家包括自己愉快, 以后的生活多一点行动,

少一点犹豫, 关键是开心就好. O(∩_∩)O 哈哈~

posted on 2016-01-19 11:09  喜ω欢  阅读(563)  评论(4)    收藏  举报