zoukankan      html  css  js  c++  java
  • 观《编程之美》,谈读后之感

        近来观《编程之美》,收获颇多,整体上还是值得称道的,对读者思维的拓展和看问题的角度助益甚多,确能体会到编程之“美”,余观“一摞烙饼的排序”,感觉甚“爽”。但读此书过程中,发现此书略有瑕疵,虽瑕不掩瑜,还是决定在此予以指出(当然也可能是我弄错了呀):

    1、本书风格不统一,建议代码全部改为伪码。

    2、表述不够流畅,愿多加润色。

    3、结构之法这章太简单。

    4、发现书中的一些错误(打字错误就不在此指出了)和可以优化的地方,现贴在此:

    (1)、在”NIM(3)两堆石头的游戏“中,代码有逻辑错误,下面是改正之后的代码(错误在注释中予以说明了):

    #include <iostream>
    #include <vector>
    #include <cmath>
    using namespace std;
    
    bool nim(int x, int y)
    {
        if(x == y) return true;
        if (x > y) {
            swap(x, y);
        }
        if (x == 1 && y == 2) {
            return false;
        }
        
        vector<int> iv;
        iv.push_back(2);
        int delta = 1;
        
        int n = 1;
        int b = 2;
        int addition = 0;
        while (x > n) {
            while (find(iv.begin(), iv.end(), ++n) != iv.end());
            ++delta;
            ++addition;
            b = n + delta;
            iv.push_back(b);
            
            if (iv.size() > 2 && addition >= 100) {
                iv.erase(remove_if(iv.begin(), iv.end(), bind2nd(less<int>(), n)), iv.end());
                addition = 0;
            }
        }
        if ((x != n) || y != b) {  //y != b 为改正之后的代码
            return true;
        }
        
        return false;
        
    }
    
    void tester1(int x, int y)
    {
        if (nim(x, y)) {
            cout<<"("<<x<<", "<<y<<") Can Win"<<endl;
        }else{
            cout<<"("<<x<<", "<<y<<") Will lose"<<endl;
        }
    }
    
    
    bool nim2(int x, int y)
    {
        if (x == y) {
            return true;
        }
        if (x > y) {
            swap(x, y);
        }
        
        double a = (1 + sqrt(5.0)) / 2;
        return x != (int)floor((y - x) * a);
    }
    
    void tester2(int x, int y)
    {
        if (nim2(x, y)) {
            cout<<"("<<x<<", "<<y<<") Can Win"<<endl;
        }else{
            cout<<"("<<x<<", "<<y<<") Will lose"<<endl;
        }
    }
    
    int main(int argc, const char * argv[]) {
        cout<<"The Tester1:"<<endl;
        tester1(1, 2);
        tester1(3, 5);
        tester1(3, 6);
        tester1(8, 10);
        tester1(8, 13);
        tester1(50, 50);
        tester1(5000, 5555);
        cout<<"The Tester2:"<<endl;
        tester2(1, 2);
        tester2(3, 5);
        tester2(3, 6);
        tester2(8, 10);
        tester2(8, 13);
        tester2(50, 50);
        tester2(5000, 5555);
        return 0;
    }
    View Code

    (2)、在”蚂蚁爬杆“中,代码有逻辑错误,下面是改正之后的代码(错误在注释中予以说明了):

    #include <iostream>
    using namespace std;
    
    
    
    void CalcTime(double length, double*  xpos, int antNum, double speed, double& min, double& max)
    {
        double totalTime = length / speed;
        max = 0;
        min = 0;
        double currentMin, currentMax;
        for (int i = 0; i < antNum; ++i) {
            currentMax = 0;
            currentMin = 0;
            if (xpos[i] > (length / 2)) {
                currentMax = xpos[i] / speed;
            }else{
                currentMax = (length - xpos[i]) / speed;
            }
            
            //这里为改正之后的代码,原书为:currentMin = totalTime - Max;
            currentMin = totalTime - currentMax;
            
            if (currentMax > max) {
                max = currentMax;
            }
            
            if (currentMin > min) { //这里为改正之后的代码,原书为:min < currentMin
                min = currentMin;
            }
        }
    }
    
    int main(int argc, const char * argv[]) {
        // insert code here...
        
        double xpos[] = {3, 7, 11, 17, 23};
        double min, max;
        CalcTime(27, xpos, 5, 1, min, max);
        cout<<min<<endl;
        cout<<max<<endl;
        return 0;
    }
    View Code

    (3)、在”计算字符串的相似度“中,加入了不需要的判断(优化在注释中予以说明了):

    #include <iostream>
    using namespace std;
    
    int inline Min(int lhs, int rhs)
    {
        return lhs < rhs ? lhs : rhs;
    }
    
    int CalculateStringDistance(char *strA, int pABegin, int pAEnd, char *strB, int pBBegin, int pBEnd)
    {
        if (pABegin > pAEnd) {
            if (pBBegin > pBEnd) {
                return 0;
            }else{
                return pBEnd - pBBegin + 1;
            }
        }
        
        if (pBBegin > pBEnd) {
            //以下注释部分为原书的代码,这里根本就不需要判断,与前面的判断重合了
    //        if (pABegin > pAEnd) {
    //            return 0;
    //        }else{
    //            return pAEnd - pABegin + 1;
    //        }
            
            return pAEnd - pABegin + 1;
        }
        
        if (strA[pABegin] == strB[pBBegin]) {
            return CalculateStringDistance(strA, pABegin + 1, pAEnd, strB, pBBegin + 1, pBEnd);
        }else{
            int t1 = CalculateStringDistance(strA, pABegin, pAEnd, strB, pBBegin + 1, pBEnd);
            int t2 = CalculateStringDistance(strA, pABegin + 1, pAEnd, strB, pBBegin, pBEnd);
            int t3 = CalculateStringDistance(strA, pABegin + 1, pAEnd, strB, pBBegin + 1, pBEnd);
            return Min(t1, Min(t2, t3)) + 1;
        }
    }
    
    
    #define ARRLEN(arr) sizeof(arr)/sizeof(int)
    int main(int argc, const char * argv[]) {
        // insert code here...
        char strA[] = "aaabcdef";
        char strB[] = "abcdefgdd";
        size_t lenA = strlen(strA);
        size_t lenB = strlen(strB);
        int len = CalculateStringDistance(strA, 0, lenA - 1, strB, 0, lenB - 1);
        cout<<len<<endl;
        return 0;
    }
    View Code

    (4)、在”数字哑谜和回文“中,number显然可以从10开始判断,在循环判断中加入break,可以降低接近五分之一的代码执行次数,读者可以自行实验:

    #include <iostream>
    #include <string.h>
    
    
    
    int main(int argc, const char * argv[]) {
        // insert code here...
        bool flag;
        bool IsUsed[10];
        int number, revert_number, t, v;
        
        for (number = 10; number < 100000; ++number) {
            flag = true;
            memset(IsUsed, 0, sizeof(IsUsed));
            t = number;
            revert_number = 0;
            for (int i = 0; i < 5; ++i) {
                v = t % 10;
                revert_number = revert_number * 10 + v;
                t /= 10;
                if (IsUsed[v]) {
                    flag = false;
                    break;  //在此处加了break,原书没有,可以减少接近五分之一的执行次数
                }else{
                    IsUsed[v] = 1;
                }
            }
            
            if (flag && (revert_number % number == 0)) {
                v = revert_number / number;
                if (v < 10 && !IsUsed[v]) {
                    printf("%d * %d = %d
    ", number, v, revert_number);
                }
            }
        }
        return 0;
    }
    View Code

    另外,还有一篇关于”求二进制数种1的个数“的文章,用二分法做的,作者独辟蹊径,见解独到,有兴趣的读者可以前往:http://blog.csdn.net/justpub/article/details/2292823

  • 相关阅读:
    操作系统知识点_用户编程接口
    操作系统知识点_内存管理
    操作系统知识点_进程管理
    LintCode 二叉树的后序遍历
    LintCode 二叉树的最大深度
    LintCode 二叉树的中序遍历
    LintCode 二叉树的前序遍历
    LintCode 删除排序链表中的重复元素
    Lintcode 二分查找
    lintcode 空格替换
  • 原文地址:https://www.cnblogs.com/wwblog/p/4350749.html
Copyright © 2011-2022 走看看