zoukankan      html  css  js  c++  java
  • 机器人上楼梯

    面试碰到的题,大意如下:

    机器人上楼梯,每步可以走1阶,2阶或者3阶,求n阶楼梯有多少种走法,列出全部走法.

    思路:

    当时想通了怎么计算多少种走法,但对于把全部走法列出来却没有什么头绪,脑子中就是觉得这题要用到递归或则是动态规划.

    f(1)      1;
    
    f(2)      1,1; 
              2;
    
    f(3)      1,2; 1,1,1;
              2,1;
              3;
    
    f(4)      1   f(3)
              2   f(2)
              3   f(1)
    
    
    f(5)      1   f(4)
              2   f(3)
              3   f(2)

    仔细分析,发现题目和阶乘很相似.分别列举1,2,3阶楼题的走法,作为基础..

    n阶(n>3),只需要考虑第一步怎么走,第一步无非就三种选择,

    1阶,2阶,3阶

    程序设计思路:

    为了避免重复计算,采用自底向上解决方案

    先求解子问题再根据子问题的解来求解父问题,参考

    /**
    *  
    * parameter:n,具体的台阶数
    *           字符串数组a[] 存放所有可能的走法
    */
    void step(string a[], int n){
        string temp1, temp2, temp3;
        a[1] = "1;";
        a[2] = "1,1;2;";
        a[3] = "1,2;1,1,1;2,1;3;";
        for (int i = 4; i <= n; i++){
            temp1 = splitAndAdd("1,", a[i-1], ";");
            temp2 = splitAndAdd("2,", a[i-2], ";");
            temp3 = splitAndAdd("3,", a[i-3], ";");
            a[i] = temp1 + temp2 + temp3;
        }
        print_result(a[n]);
    }

    为避免重复求解,使用字符串数组存放每阶的走法,为便于后续处理,不同走法之间以";"分割,字符串中;有多少个就代表有多少种走法

    显然a[4] = 1,a[3] + 2,a[2]+ 3,a[1]

    a[4]的所有解法如下,关键在于怎么把1,2,3加到每种解法的前面

    1, 1,2
    1, 1,1,1
    1, 2,1
    1, 3 
    
    2, 1,1
    2, 2
    
    3, 1

    设计函数splitAndAdd,该函数主要思路将原来的解法字符串根据";"进行切片,得到个每种解法并保存,然后遍历每种解法,加上新的步法,并补充分隔符";"

    注:c++ 没有像java现成的切片函数,借用c中的strtok实现,可参考

     1 /**
     2 *
     3 * parameter:pre,要加入的字符
     4 *           str,已有解法字符串
     5 *           pattern,各种解法的分隔符
     6 */
     7 
     8 string splitAndAdd(string pre, string &str, string pattern){
     9     string res;
    10     std::vector<std::string> resultVec;
    11     char * strc = new char[strlen(str.c_str()) + 1];
    12     strcpy_s(strc, strlen(str.c_str()) + 1, str.c_str());
    13 
    14     char* tmpStr = strtok(strc, pattern.c_str());
    15     while (tmpStr != NULL)
    16     {
    17         resultVec.push_back(pre + std::string(tmpStr));
    18         tmpStr = strtok(NULL, pattern.c_str());
    19     }
    20     for (string s : resultVec){
    21         res += s + ";";
    22     }
    23     return res;
    24 }

    程序运行结果:5阶梯为例

    1,1,1,2
    1,1,1,1,1
    1,1,2,1
    1,1,3
    1,2,1,1
    1,2,2
    1,3,1
    2,1,2
    2,1,1,1
    2,2,1
    2,3
    3,1,1
    3,2
    
    total path num:13

    完整程序

    #include<iostream>
    #include<string>
    #include<vector>
    using std::cin;
    using std::cout;
    using std::endl;
    using std::string;
    using std::vector;
    
    /**
    *
    * parameter:pre,要加入的字符
    *           str,已有解法字符串
    *           pattern,各种解法的分隔符
    */
    
    string splitAndAdd(string pre, string &str, string pattern){
        string res;
        std::vector<std::string> resultVec;
        char * strc = new char[strlen(str.c_str()) + 1];
        strcpy_s(strc, strlen(str.c_str()) + 1, str.c_str());
    
        char* tmpStr = strtok(strc, pattern.c_str());
        while (tmpStr != NULL)
        {
            resultVec.push_back(pre + std::string(tmpStr));
            tmpStr = strtok(NULL, pattern.c_str());
        }
        for (string s : resultVec){
            res += s + ";";
        }
        return res;
    }
    
    void print_result(string &res){
        string strs = res;
        size_t pos = res.find(";");
        size_t size = res.size();
        int count = 0;
        while (pos != std::string::npos){
            count++;
            cout << strs.substr(0, pos) << endl;
            strs = strs.substr(pos + 1, size);
            pos = strs.find(";");
        }
        cout << endl << "total path num:" << count << endl;
    }
    
    /**
    *  
    * parameter:n,具体的台阶数
    *           字符串数组a[] 存放所有可能的走法
    */
    void step(string a[], int n){
        string temp1, temp2, temp3;
        a[1] = "1;";
        a[2] = "1,1;2;";
        a[3] = "1,2;1,1,1;2,1;3;";
        for (int i = 4; i <= n; i++){
            temp1 = splitAndAdd("1,", a[i-1], ";");
            temp2 = splitAndAdd("2,", a[i-2], ";");
            temp3 = splitAndAdd("3,", a[i-3], ";");
            a[i] = temp1 + temp2 + temp3;
        }
        print_result(a[n]);
    }
    
    
    #define N 1000
    int main()
    {
        string steps[N];
        step(steps, 5);
        return 0;
    }
    View Code
  • 相关阅读:
    iOS数据持久化—FMDB框架的简单介绍
    iOS数据持久化—SQLite常用的函数
    多段图动态规划dp
    Cucumber测试驱动开发
    敏捷开发XP
    Android 小票打印USB
    TextInputLayout 用法
    Snackbar 提醒
    PermissionDispatcher 运行时权限框架
    Tinker 热修复
  • 原文地址:https://www.cnblogs.com/hixin/p/7565083.html
Copyright © 2011-2022 走看看