하스켈을 배우려면 프로그래밍 문제를 해결해 왔습니다. Hackerrank에서 발견 된 한 가지 문제를 해결하기 위해 1000 개 요소 목록의 요소를 필터링하는 동안 시간 테스트를 통과하지 못했습니다.목록의 필터링을 최적화하는 방법
문제 문은입니다 : 요소의 목록 이상 K 번 표시 자들을 필터링 및 외관의 순서대로 인쇄에서. 나는이 코드를 개선 할 수있는 알고 싶습니다
import qualified Data.ByteString.Char8 as BSC
import Data.Maybe (fromJust)
import Data.List (intercalate, elemIndices, foldl')
import qualified Data.Set as S
-- Improved version of nub
nub' :: (Ord a) => [a] -> [a]
nub' = go S.empty
where go _ [] = []
go s (x:xs) | S.member x s = go s xs
| otherwise = x : go (S.insert x s) xs
-- Extract Int from ByteString
getIntFromBS :: BSC.ByteString -> Int
getIntFromBS = fst . fromJust . BSC.readInt
{-
Parse read file:
a k1
n1 n2 n3 n4 ...
c k2
m1 m2 m3 m4 ...
into appropriate format:
[(k1, [n1,n2,n3,n4]), (k2, [m1,m2,m3,m4])]
-}
createGroups :: [BSC.ByteString] -> [(Int, [Int])]
createGroups [] = []
createGroups (p:v:xs) =
let val = getIntFromBS $ last $ BSC.split ' ' p
grp = foldr (\x acc -> getIntFromBS x : acc) [] $ BSC.split ' ' v
in (val, grp) : createGroups xs
solve :: (Int, [Int]) -> String
solve (k, v) = intercalate " " $ if null res then ["-1"] else res
where
go n acc =
if length (elemIndices n v) > k
then show n : acc
else acc
res = foldr go [] (nub' v)
fullSolve :: [BSC.ByteString] -> [String]
fullSolve xs = foldl' (\acc tupla -> acC++ [solve tupla]) [] $ createGroups xs
main = do
BSC.getContents >>= mapM_ putStrLn . fullSolve . drop 1 . BSC.lines
:
지금까지 왔어요 가장
이 코드입니다. map, vector, 구문 분석을 사용하여 많은 변종을 시도해 보았습니다. 파일에서 읽은 문자열을Int
으로 파싱하지 않았지만, 표시된 코드는 내가 가진 최고입니다.
'acC++ [solve tupla]'부분은 나에게 걱정 스럽다. 런타임 성능이 좋지 않을 것이다. 대신에 'Data.Seq' 사용을 고려하십시오 – bheklilr
왜 특정 부분이 당신을 걱정하는지 설명해 주시겠습니까? 어떻게 알았어? – OneEyeQuestion
단일 링크 된 목록 (하스켈 목록이 무엇인지)의 끝에 단일 요소를 연결하는 것은 O (n) 작업입니다. 요소를 추가 할 때마다 전체 목록을 탐색해야합니다. 요소를 선행 (또는 consing)하는 것은 O (1)입니다. 하스켈 코드를 읽을 때 이러한 종류의 세부 사항이 두드러지며'++ [single element] '는 경험으로 상당히 눈에 띄게됩니다. – bheklilr