面试笔试做不出长整数加法的是不是 coding 能力就基本当没有了?

2020-08-20 11:02:09 +08:00
 phpfpm

最近面试,按说候选人背景也都不错吧。

我们对算法要求没那么高,业务代码为主。

因此对于各种语言的候选人,我基本都会问一道长整数加法的问题。

俩数相加,都没有符号 /没有小数点 /字符串表示 返回和 /用字符串表示

这题难吗?

考察的知识点点挺广的:

字符串 /数组操作,循环控制,流程逻辑,边界条件等等。

这也基本上是编程的时候经常能遇到的问题。

但是我遇到的面试者写的千奇百怪的都有:

等等吧

所以如果你遇到这个题,如何优雅的写一个 a+b?

稍后我写一个我自己花了一小点时间写的答案,八行,没有很过分的压缩代码 我的代码大概长这样:

function add(a, b) {
    let ...
    some magic {
    	cast something
        cast other
    }
    return ...
}

正经逻辑三四行写完,晚一些我贴条的方式公布我的答案。

如果要你写,你写啥?

22777 次点击
所在节点    程序员
321 条回复
banishee
2020-08-20 11:32:53 +08:00
@hytex 请问这个代码考虑最后一个进位了吗
hytex
2020-08-20 11:34:18 +08:00
@banishee add = 0
phpfpm
2020-08-20 11:34:46 +08:00
@lijialong1313 满地都是大数加法算法了吧——没跟上。
我们不招 c 的,不过有年头比较长嵌入式北京的我会随口问一句 C 的 VLA
形如
```
struct foo {
char bar;
int[0] baz;
};

```
这个 trick 了
(我也只会这个了 hhh
no1xsyzy
2020-08-20 11:39:36 +08:00
主要是 reverse 太方便了(

https://repl.it/repls/ExpensiveWorriedAgents
islxyqwe
2020-08-20 11:39:48 +08:00
addr 0 [] xs = reverse xs
addr n [] xs = addr 0 (show n) xs
addr n xs [] = addr n [] xs
addr n (x:xs) (y:ys) = (addr left xs ys) ++ (show digit) where
(left, digit) = divMod ((read [x] ::Integer) + (read [y] ::Integer) + n) 10
add a b = addr 0 (reverse a) (reverse b)
ytmsdy
2020-08-20 11:41:24 +08:00
我记得当年刚刚开始玩 acm 的时候,zoj 上的第一道题就是大数 a+b 。那时候花了快 3 天才搞完!
现在想想,从最后一位开始模拟手工计算的过程就好了!
cyrbuzz
2020-08-20 11:41:52 +08:00
```
function add(a, b) {
let max = Math.max(a.length, b.length);
a = a.padStart(max, '0');
b = b.padStart(max, '0');

let result = ''
let pad = 0

for (let i=max-1; i>-1; i--) {
let c = String(Number(a[i])+Number(b[i])+Number(pad))
c = c.padStart(2, '0')
pad = c[0]
result = `${c[1]}${result}`
}

return `${pad === '0' ? '' : pad}${result}`
}

console.log(add('1001', '200'))
```
no1xsyzy
2020-08-20 11:42:25 +08:00
@no1xsyzy #24 没编辑前后文断裂
这个是不带 reverse 的,还是 padding
但结构上用了一种诡异的方式来解决所有进位问题
phpfpm
2020-08-20 11:43:19 +08:00
@islxyqwe 膜拜 Scala 大佬(其实我也不知道叫啥,没准是 scheme 之类的
phpfpm
2020-08-20 11:45:01 +08:00
@no1xsyzy
@cyrbuzz
@ytmsdy
@islxyqwe
@no1xsyzy
@hytex
@lijialong1313
@yhxx
@dartabe
@Jooooooooo
@luckyrayyy
@march1993
@islxyqwe

我在贴条 Append 的地方写了我的解法了——很遗憾,那边好像不支持 markdown 。。

```
function add(a, b) {
let pos = 0, res = ''
while(a.length > pos || b.length > pos) {
let carry = res.length - pos++
res = (~~a[a.length - pos] + ~~b[b.length - pos] + carry) + res.substring(carry)
}
return res
}
```

希望回复能好看点。。。。
no1xsyzy
2020-08-20 11:55:27 +08:00
@phpfpm #30 APPEND 需要自己选择语法是 Default 还是 Markdown
这个用 res.length 来记录是否有进位有点奇技淫巧了
banishee
2020-08-20 11:57:06 +08:00
@phpfpm 请问这不会造成数组边界溢出吗
no1xsyzy
2020-08-20 11:58:27 +08:00
@phpfpm #30 也不能说奇技淫巧,就是在各种地方找到能放信息的地方
还是 add(x,y) = x&y<<1 + x|y 更奇技淫巧……
no1xsyzy
2020-08-20 11:59:45 +08:00
@banishee #32 唯一处理数组的地方是取 a[] 和 b[],JS 下溢出是 undefined, ~~x 之后就是 0,这点上无法替换为 +x,因为 +x 会变成 NaN
murmur
2020-08-20 12:00:21 +08:00
有大整数类为啥要自己写,你能保证写出来的过的单元测试比库更多么
wutiantong
2020-08-20 12:02:21 +08:00
std::string add(std::string a, std::string b) {
std::string result;
auto a_i = a.rbegin(), b_i = b.rbegin();
char ten = 0;
while (true) {
char x = 0;
if (a_i != a.rend()) x = (*a_i++) - '0';
char y = 0;
if (b_i != b.rend()) y = (*b_i++) - '0';
auto c = x + y + ten;
if (c == 0) break;
else if (c > 9) {
c -= 10;
ten = 1;
} else ten = 0;
result.insert(result.begin(), c + '0');
}
return result;
}
lijialong1313
2020-08-20 12:02:52 +08:00
@phpfpm 我写了一个 c 语言的: https://paste.ubuntu.com/p/YjF5DZqXnR/
YuTengjing
2020-08-20 12:09:48 +08:00
这道题很常见啊,不会做说明没怎么准备面试算法
XiaoxiaoPu
2020-08-20 12:12:04 +08:00
确实不难吧,我大一就能做高精度浮点数的加减乘除、三角函数、指数、对数函数了,虽然效率一般。
mazyi
2020-08-20 12:15:24 +08:00
面试笔试做不出长整数加法的是不是 coding 能力就基本当没有了?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/699860

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX