学习Erlang,我正在解决一个简单的问题,我想出了这个解决方案:
%%%------------------------------------------------------------------
%%% @doc https://leetcode.com/problems/add-two-numbers/
%%%
%%% @end
%%%------------------------------------------------------------------
-module(add_two_numbers).
-define(BASE10, 10).
-export([main/2]).
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
-endif.
-spec main(L1 :: nonempty_list(non_neg_integer()), L2 :: nonempty_list(non_neg_integer())) -> list().
%%%==================================================================
%%% Export
%%%==================================================================
main(L1, L2) ->
loop(L1, L2, 0, []).
-ifdef(TEST).
main_test() ->
?assertEqual([0, 2, 1, 2, 1, 1], add_two_numbers:main([9, 6, 9, 5, 9], [1, 5, 1, 6, 1])),
?assertEqual([3, 6, 9, 7, 5], add_two_numbers:main([4, 1, 8, 7, 2], [9, 4, 1, 0, 3])),
?assertEqual([6, 7, 9, 0, 1], add_two_numbers:main([2, 2, 3, 3], [4, 5, 6, 7])),
?assertEqual([6, 3, 7, 4, 1], add_two_numbers:main([4, 1, 0, 8], [2, 2, 7, 6])),
?assertEqual([2, 7, 9, 1], add_two_numbers:main([2, 7, 1, 0], [0, 0, 8, 1])),
?assertEqual([8, 9, 9, 1], add_two_numbers:main([9, 9, 9], [9, 9, 9])),
?assertEqual([7, 1, 6, 1], add_two_numbers:main([9, 3, 7], [8, 7, 8])),
?assertEqual([3, 5, 6, 1], add_two_numbers:main([6, 6, 6], [7, 8, 9])),
?assertEqual([0, 0, 0], add_two_numbers:main([0, 0, 0], [0, 0, 0])),
?assertEqual([7, 0, 8], add_two_numbers:main([2, 4, 3], [5, 6, 4])),
?assertEqual([0, 2, 2], add_two_numbers:main([0, 1], [0, 1, 2])),
?assertEqual([0, 1, 1], add_two_numbers:main([4, 6], [6, 4])),
?assertEqual([0, 0, 1], add_two_numbers:main([1], [9, 9])),
?assertEqual([0, 1], add_two_numbers:main([], [0, 1])),
?assertEqual([], add_two_numbers:main([], [])),
?assertError(badarith, add_two_numbers:main([0, 1, 2], ["", 5, 6])).
-endif.
%%%==================================================================
%%% Internal
%%%==================================================================
loop([H1 | T1], [H2 | T2], C, R) when H1 + H2 + C >= ?BASE10 ->
loop(T1, T2, 1, R ++ [H1 + H2 + C - ?BASE10]);
loop([], [H | T], C, R) when H + C >= ?BASE10 ->
loop([], T, 1, R ++ [H + C - ?BASE10]);
loop([H | T], [], C, R) when H + C >= ?BASE10 ->
loop([], T, 1, R ++ [H + C - ?BASE10]);
loop([H1 | T1], [H2 | T2], C, R) ->
loop(T1, T2, 0, R ++ [H1 + H2 + C]);
loop([], [H | T], C, R) ->
loop([], T, 0, R ++ [H + C]);
loop([H | T], [], C, R) ->
loop([], T, 1, R ++ [H + C]);
loop([], [], C, R) when C > 0 -> R ++ [C];
loop([], [], _, R) -> R.
困扰我的是我必须定义多少loop
个电话。最终可能会有更好的解决方案。
我的问题:如果某个条件在某个范围内,我可以用case
- of
告诉我吗?像这样的东西,例如:
X = H1 + H2 + C,
case X of
X >= 10 -> blah;
_ -> ummm
end.
更新
这就是我想要实现的目标:
loop([H1 | T1], [H2 | T2], C, R) ->
case H1 + H2 + C >= ?BASE10 of
true -> loop(T1, T2, 1, R ++ [H1 + H2 + C - ?BASE10]);
false -> loop(T1, T2, 0, R ++ [H1 + H2 + C])
end;
loop([], [H | T], C, R) ->
case H + C >= ?BASE10 of
true -> loop([], T, 1, R ++ [H + C - ?BASE10]);
false -> loop([], T, 0, R ++ [H + C])
end;
loop([H | T], [], C, R) ->
case H + C >= ?BASE10 of
true -> loop(T, [], 1, R ++ [H + C - ?BASE10]);
false -> loop(T, [], 0, R ++ [H + C])
end;
loop([], [], C, R) ->
case C > 0 of
true -> R ++ [C];
false -> R
end.
......不确定它是否更好。
答案 0 :(得分:2)
你可以使用这个小技巧
SELECT d.datname AS Name, pg_catalog.pg_get_userbyid(d.datdba) AS Owner,
CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')
THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))
ELSE 'No Access'
END AS SIZE
FROM pg_catalog.pg_database d
ORDER BY
CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')
THEN pg_catalog.pg_database_size(d.datname)
ELSE NULL
END DESC -- nulls first
LIMIT 20
注意我不使用loop([], [], 0, R) -> lists:reverse(R);
loop([], [], 1, R) -> lists:reverse(R, [1]);
loop([], L2, C, R) ->
loop([0], L2, C, R);
loop(L1, [], C, R) ->
loop(L1, [0], C, R);
loop([H1 | T1], [H2 | T2], C, R) ->
case H1 + H2 + C of
S when S >= ?BASE10 ->
loop(T1, T2, 1, [S - ?BASE10 | R]);
S ->
loop(T1, T2, 0, [S | R])
end.
模式,因为它是坏习惯使它成为O(N ^ 2)(见[1])。从性能的角度来看,如果必须使用Acc++[X]
,则不需要尾部调用优化,因此这个非尾部调用版本应该与尾部调用优化一样快,或者在某些平台上更快:
lists:reverse/1,2
或者您可以更进一步,删除案例并获取main(L1, L2) ->
loop(L1, L2, 0).
loop([], [], 0) -> [];
loop([], [], 1) -> [1];
loop([], L2, C) ->
loop([0], L2, C);
loop(L1, [], C) ->
loop(L1, [0], C);
loop([H1 | T1], [H2 | T2], C) ->
case H1 + H2 + C of
X when X >= ?BASE10 ->
[ X - ?BASE10 | loop(T1, T2, 1) ];
X ->
[ X | loop(T1, T2, 0) ]
end.
+ 0
[1]:尝试使用您的代码loop([], [], 0) -> [];
loop([], [], 1) -> [1];
loop([], [H | T], C) ->
loop_([], T, H + C);
loop([H | T], [], C) ->
loop_([], T, H + C);
loop([H1 | T1], [H2 | T2], C) ->
loop_(T1, T2, H1 + H2 + C).
loop_(L1, L2, S) when S >= ?BASE10 ->
[ S - ?BASE10 | loop(L1, L2, 1) ];
loop_(L1, L2, S) ->
[ S | loop(L1, L2, 0) ].
。在我的代码中,它需要3.5毫秒,而你的需要33秒。
答案 1 :(得分:1)
您可以使用2个辅助函数(不确定它是否更高效,可能更容易阅读):
loop([H1 | T1], [H2 | T2], C, R) ->
N = H1 + H2 + C,
loop(T1, T2, carry(N), R ++ sum(N));
loop([], [H | T], C, R) ->
N = H + C,
loop([], T, carry(N), R ++ sum(N));
loop([H | T], [], C, R) ->
N = H + C,
loop(T, [], carry(N), R ++ sum(N));
loop([], [], 0, R) ->
R;
loop([], [], C, R) ->
R ++ [C].
carry(N) when N >= ?BASE10 -> 1;
carry(_) -> 0.
sum(N) when N >= ?BASE10 -> [N - ?BASE10];
sum(N) -> [N].