一道笔试题: 输入一串数字,求对应英文字母出现的可能性 z = {'a':1, 'b':2, .... , 'z':26}, 输入: 123,输出: abc, lc, aw(l: 12, w: 23) - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
qiShaMingZi
V2EX    Python

一道笔试题: 输入一串数字,求对应英文字母出现的可能性 z = {'a':1, 'b':2, .... , 'z':26}, 输入: 123,输出: abc, lc, aw(l: 12, w: 23)

  •  
  •   qiShaMingZi 2019-11-12 01:22:10 +08:00 4905 次点击
    这是一个创建于 2228 天前的主题,其中的信息可能已经有所发展或是发生改变。
    17 条回复    2019-11-12 12:56:06 +08:00
    xiaoming1992
        1
    xiaoming1992  
       2019-11-12 01:41:50 +08:00 via Android
    func
    const result = []
    const availTuples = [...]
    availTuples.foreach
    const (a, b) = tuple
    result.push(map(a), func(b))
    return result
    xiaoming1992
        2
    xiaoming1992  
       2019-11-12 01:42:21 +08:00 via Android   1
    艹了,我的空格缩进都给我吃掉了。。。
    lihongming
        3
    lihongming  
       2019-11-12 02:05:27 +08:00 via iPhone
    第一反应是迭代。
    每次截取 1-2 位数字( 2 位数字需要<=26 ),然后把剩下的数字迭代给自己。

    时间、空间复杂度都是 O(N),准确来说是 2N,可能效率不是最高,但很容易想
    geelaw
        4
    geelaw  
       2019-11-12 02:34:17 +08:00 via iPhone
    @lihongming #3 这个问题的输出长度可以达到 Omega(1.6^n),因此不可能时间是 O(n)。

    此外这个输出长度也表示空间至少需要 Omega(n),因此朴素的算法已经是最佳。
    NVDA
        5
    NVDA  
       2019-11-12 02:35:29 +08:00 via iPhone
    lihongming
        6
    lihongming  
       2019-11-12 02:38:23 +08:00
    @Mirage09 哈哈哈,第一次见这么多负分的题,竟然还有公司拿来笔试?
    lihongming
        7
    lihongming  
       2019-11-12 02:53:26 +08:00
    @geelaw 是的,我想简单了,迭代的时间复杂度应该是 O(N^2)
    NVDA
        8
    NVDA  
       2019-11-12 03:53:26 +08:00   1
    mskf
        9
    mskf  
       2019-11-12 03:53:30 +08:00
    刚试了下,反向 dp 应该是最简单的。。。不是很理解为啥这题这么多踩啊,是不是以前的测试数据有问题
    trn4
        10
    trn4  
       2019-11-12 05:39:12 +08:00 via iPhone
    最基本的 dp
    caixiangyu17
        11
    caixiangyu17  
       2019-11-12 07:30:34 +08:00
    动态规划,根据第一位数值,分解成两个子问题
    char(a[0])+f(a[1...n])
    char(a[0]*10+a[1]) + f(a[2...n])
    细节就不说了,会动态规划不难
    siriussilen
        12
    siriussilen  
       2019-11-12 09:04:47 +08:00   3
    这道题,可以从记忆化递归的角度来理解,比如对于一个字符串 F("2213")=5, 可以分解为 F("213")和 F("13")两个子问题,在 F("213")这个子问题中又可以分为 F("13")和 F("3")两个子子问题,F("13")这个子子问题和 F("13")子问题是重复的,因而可以考虑使用记忆化搜索或动态规划来解决这个问题。

    特别地,如果一个数中的一个前缀和两个前缀都是合法的,那么这个值等于斐波那契数列+1(此时解空间实际上就等价于斐波那契数列的状态转移方式),例如,f("12121212")=Fibonacci number(8+1) = 34

    ```cpp
    class Solution {
    public:
    int numDecodings(string s) {
    if(s.length() == 0) return 0;
    unordered_map<string, int> ways;
    ways[""] = 1;
    function<int(const string &s)> dfs = [&](const string& s){
    if(ways.count(s)) return ways[s];
    if(s[0] == '0') return 0; // 第一位是 0,这是非法的返回 0
    if(s.length() == 1) return 1; // e.g. 1-9,返回一种方式
    int w = dfs(s.substr(1)); // 把第一位去掉,子问题 1
    int prefix = stoi(s.substr(0,2)); // 取前两位,子问题 2
    if(prefix <= 26) w += dfs(s.substr(2)); // 检查是否合法
    ways[s] = w;
    return w;
    };
    return dfs(s);
    }
    };
    ```

    执行用时 :8 ms, 在所有 cpp 提交中击败了 37.55%的用户
    内存消耗 :16.5 MB, 在所有 cpp 提交中击败了 5.18%的用户


    记忆化搜索比较好理解,此外我的思考难免存在不足,欢迎批评指教
    knva
        13
    knva  
       2019-11-12 09:57:32 +08:00
    首先分割这些字符
    0 位为 0 直接返回 0 ;
    若 s[i-1]==1 则 +1
    若 s[i-1]==2 并且 s[i]<=6 +1

    字符串中有 0 则特殊处理
    petelin
        14
    petelin  
       2019-11-12 11:37:56 +08:00 via iPhone
    这难道不是回溯吗
    justseemore
        15
    justseemore  
       2019-11-12 11:56:01 +08:00
    - -,这么多高大上,只有我是 kv 交换,然后输出 123 的排列组合中单个小于 26 的组合么..
    petelin
        16
    petelin  
       2019-11-12 12:54:03 +08:00
    ```
    func numDecodings(s string) (ans int) {
    backtrace(s, &ans)br /> return
    }

    func backtrace(s string, ans *int){
    if len(s) == 0{
    *ans++
    return
    }
    if '1' <= s[0] && s[0] <= '9'{
    backtrace(s[1:], ans)
    }

    if len(s) > 1{
    if (s[0] == '1') || (s[0] == '2' && '0' <= s[1] && s[1] <= '6') {
    backtrace(s[2:], ans)
    }
    }
    }```

    这个叫不叫回溯? 有没有学院派大佬
    petelin
        17
    petelin  
       2019-11-12 12:56:06 +08:00
    我理解这个应该是搜索. 或者就是递归
    然后如果用动态规划写, 这题就是一个 fib 的变种. fib(3) = fib(2) + fib(1) fib(1)不一定能加起来, 因为前两个数不一定在[1,26]
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     889 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 41ms UTC 21:30 PVG 05:30 LAX 13:30 JFK 16:30
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86