心血来潮的一天打开阔别已久的Leetcode,想搞个Easy爽爽,发现编译语言支持Erlang以后便发现了新世界,开冲!本篇干货较多,使用Erlang listAPI、maps和原生array(底层为元组实现)
直接祭出了我之前自己写过的Erlang解决最大岛屿问题
题号是695,当时用Java和Erlang都有尝试,题目里那个案例是可以通过
题目
695.岛屿的最大面积
给你一个大小为 m x n 的二进制矩阵 grid 。
岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在 水平或者竖直的四个方向上 相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。
岛屿的面积是岛上值为 1 的单元格的数目。
计算并返回 grid 中最大的岛屿面积。如果没有岛屿,则返回面积为 0 。
示例 1:
输入:grid = [[0,0,1,0,0,0,0,1,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,1,1,0,1,0,0,0,0,0,0,0,0],[0,1,0,0,1,1,0,0,1,0,1,0,0],[0,1,0,0,1,1,0,0,1,1,1,0,0],[0,0,0,0,0,0,0,0,0,0,1,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,0,0,0,0,0,0,1,1,0,0,0,0]]
输出:6
解释:答案不应该是 11 ,因为岛屿只能包含水平或垂直这四个方向上的 1 。
示例 2:
输入:grid = [[0,0,0,0,0,0,0,0]]
输出:0
尝试
方法一 list加坐标
-spec max_area_of_island(Grid :: [[integer()]]) -> integer().
max_area_of_island(List) ->
Length1 = length(List),
[H | _] = List,
Length2 = length(H),
IndexList = make_index1(List, Length1, Length2, 0, 0, []),
Max = check(IndexList, Length1, Length2, 0, 0).
make_index1([H | T], Length1, Length2, L1, L2, Res) ->
NRes = make_index2(H, Length1, Length2, L1, L2, Res),
make_index1(T, Length1, Length2, L1 + 1, L2, NRes);
make_index1([], _, _, _, _, Res) -> Res.
make_index2([H | T], Length1, Length2, L1, L2, Res) ->
make_index2(T, Length1, Length2, L1, L2 + 1, Res ++ [{{L1, L2}, H}]);
make_index2([], _, _, _, _, Res) -> Res.
check(List, Length1, Length2, I, Max) when I < Length1 ->
{List1, NMax} = check1(List, Length1, I, Length2, 0, Max),
check(List1, Length1, Length2, I + 1, NMax);
check(_List, _L1, _L2, _I, Max) -> Max.
check1(List, Length1, I, Length2, II, Max) when II < Length2 ->
case lists:keyfind({I, II}, 1, List) of
{_, 1} ->
{List1, TMax} = dfs(List, I, II, Length1, Length2),
NMax = max(Max, TMax),
{List1, NMax};
%% case NMax /= Max of
%% true ->
%% io:format("--------------{~w,~w}-------~w-~w-------~n", [I, II, Max, NMax]);
%% false ->
%% io:format("--------------{~w,~w}-------~w-~w-------~n", [I, II, Max, NMax])
%% end;
{_, 0} ->
NMax = Max,
List1 = List,
{List1, NMax}
end,
check1(List1, Length1, I, Length2, II + 1, NMax);
check1(List, _Length1, _I, _Length2, _II, Max) -> {List, Max}.
dfs(List, I, II, Length1, Length2) ->
case I < 0 orelse II < 0 orelse I >= Length1 orelse II >= Length2 of
true ->
{List, 0};
false ->
case lists:keyfind({I, II}, 1, List) of
{_, 1} ->
%% io:format("================{~w,~w}==================~n", [I, II]),
TempList = lists:keyreplace({I, II}, 1, List, {{I, II}, 0}),
%% io:format("--------------~w---------------~n", [TempList]),
Count = 1,
{TempList1, TCount1} = dfs(TempList, I + 1, II, Length1, Length2),
Count1 = Count + TCount1,
{TempList2, TCount2} = dfs(TempList1, I - 1, II, Length1, Length2),
Count2 = Count1 + TCount2,
{TempList3, TCount3} = dfs(TempList2, I, II + 1, Length1, Length2),
Count3 = Count2 + TCount3,
{TempList4, TCount4} = dfs(TempList3, I, II - 1, Length1, Length2),
Count4 = Count3 + TCount4,
{TempList4, Count4};
{_, 0} ->
{List, 0}
end
end.
兴冲冲的提交一下,
2612ms好家伙,听说map比较快,那我们试试再来!
方法二 map加坐标
-spec max_area_of_island(Grid :: [[integer()]]) -> integer().
max_area_of_island(List) ->
Length1 = length(List),
[H | _] = List,
Length2 = length(H),
Map = maps:new(),
NewMap = make_index3(List, Length1, Length2, 0, 0, Map),
Max = map_check(NewMap, Length1, Length2, 0, 0).
make_index3([H | T], Length1, Length2, L1, L2, Map) ->
NRes = make_index4(H, Length1, Length2, L1, L2, Map),
make_index3(T, Length1, Length2, L1 + 1, L2, NRes);
make_index3([], _, _, _, _, Res) -> Res.
make_index4([H | T], Length1, Length2, L1, L2, Res) ->
make_index4(T, Length1, Length2, L1, L2 + 1, maps:put({L1,L2}, H, Res));
make_index4([], _, _, _, _, Res) -> Res.
map_check(Map, Length1, Length2, I, Max) when I < Length1 ->
{Map1 ,NMax} = map_check1(Map, Length1, I, Length2, 0, Max),
map_check(Map1, Length1, Length2, I + 1, NMax);
map_check(_List, _L1, _L2, _I, Max) -> Max.
map_check1(Map, Length1, I, Length2, II, Max) when II < Length2 ->
case maps:get({I, II}, Map) of
1 ->
{Map1, TMax} = map_dfs(Map, I, II, Length1, Length2),
NMax = max(Max, TMax);
0 ->
NMax = Max,
Map1 = Map
end,
map_check1(Map1, Length1, I, Length2, II + 1, NMax);
map_check1(Map, _Length1, _I, _Length2, _II, Max) -> {Map, Max}.
map_dfs(Map, I, II, Length1, Length2) ->
case I < 0 orelse II < 0 orelse I >= Length1 orelse II >= Length2 of
true ->
{Map, 0};
false ->
case maps:get({I, II}, Map) of
1 ->
%% io:format("================{~w,~w}==================~n", [I, II]),
TempMap = maps:put({I, II}, 0, Map),
%% TempList = lists:keyreplace({I, II}, 1, List, {{I, II}, 0}),
%% io:format("--------------~w---------------~n", [TempList]),
Count = 1,
{TempMap1, TCount1} = map_dfs(TempMap, I + 1, II, Length1, Length2),
Count1 = Count + TCount1,
{TempMap2, TCount2} = map_dfs(TempMap1, I - 1, II, Length1, Length2),
Count2 = Count1 + TCount2,
{TempMap3, TCount3} = map_dfs(TempMap2, I, II + 1, Length1, Length2),
Count3 = Count2 + TCount3,
{TempMap4, TCount4} = map_dfs(TempMap3, I, II - 1, Length1, Length2),
Count4 = Count3 + TCount4,
{TempMap4, Count4};
0 ->
{Map, 0}
end
end.
再次提交,看看这次过了多少
260ms,舒服了,但是听说erlang自己实现了array,那再试试看呗
方法三 array实现
-spec max_area_of_island(Grid :: [[integer()]]) -> integer().
max_area_of_island(List) ->
Length1 = length(List),
[H | _] = List,
Length2 = length(H),
Map = maps:new(),
Arr = array:new(),
NewArr = make_index5(List, Length1, Length2, 0, 0, Arr),
%% io:format("~w",[NewArr]),
Max = arr_check(NewArr, Length1, Length2, 0, 0).
%% @doc array实现
make_index5([H | T], Length1, Length2, L1, L2, Arr) ->
NRes = make_index6(H, Length1, Length2, L1, L2, array:set(L1, array:new(), Arr)),
make_index5(T, Length1, Length2, L1 + 1, L2, NRes);
make_index5([], _, _, _, _, Res) -> Res.
make_index6([H | T], Length1, Length2, L1, L2, Arr) ->
Tarr = array:get(L1, Arr),
Tarr1 = array:set(L2, H, Tarr),
NewArr = array:set(L1, Tarr1, Arr),
make_index6(T, Length1, Length2, L1, L2 + 1, NewArr);
make_index6([], _, _, _, _, Res) -> Res.
arr_check(Arr, Length1, Length2, I, Max) when I < Length1 ->
{Arr1, NMax} = arr_check1(Arr, Length1, I, Length2, 0, Max),
arr_check(Arr1, Length1, Length2, I + 1, NMax);
arr_check(_List, _L1, _L2, _I, Max) -> Max.
arr_check1(Arr, Length1, I, Length2, II, Max) when II < Length2 ->
case array:get(II,array:get(I, Arr)) of
1 ->
{Arr1, TMax} = arr_dfs(Arr, I, II, Length1, Length2),
NMax = max(Max, TMax);
0 ->
NMax = Max,
Arr1 = Arr
end,
arr_check1(Arr1, Length1, I, Length2, II + 1, NMax);
arr_check1(Arr, _Length1, _I, _Length2, _II, Max) -> {Arr, Max}.
arr_dfs(Arr, I, II, Length1, Length2) ->
case I < 0 orelse II < 0 orelse I >= Length1 orelse II >= Length2 of
true ->
{Arr, 0};
false ->
case array:get(II,array:get(I,Arr)) of
1 ->
%% io:format("================{~w,~w}==================~n", [I, II]),
A1 = array:get(I, Arr),
A2 = array:set(II, 0, A1),
NewArr = array:set(I, A2, Arr),
%% TempList = lists:keyreplace({I, II}, 1, List, {{I, II}, 0}),
%% io:format("--------------~w---------------~n", [TempList]),
Count = 1,
{NewArr1, TCount1} = arr_dfs(NewArr, I + 1, II, Length1, Length2),
Count1 = Count + TCount1,
{NewArr2, TCount2} = arr_dfs(NewArr1, I - 1, II, Length1, Length2),
Count2 = Count1 + TCount2,
{NewArr3, TCount3} = arr_dfs(NewArr2, I, II + 1, Length1, Length2),
Count3 = Count2 + TCount3,
{NewArr4, TCount4} = arr_dfs(NewArr3, I, II - 1, Length1, Length2),
Count4 = Count3 + TCount4,
{NewArr4, Count4};
0 ->
{Arr, 0}
end
end.
提交!
好!晚安!