В Haskell есть что-то неподходящее, которое (как и многие мои идеи), вероятно, может быть более совершенным и оптимизированным.Это идет что-то вроде этого:
- Сортировка массива (я получил интересные результаты, пытаясь как восходящие и нисходящие)
- BN = первые N элементов массива
- B (I), при г> N = лучший кандидат; где (предполагая целые числа), если они меньше 1, кандидаты сравниваются по абсолютной величине их сумм; если они равны 1 или более, по их сумме; и если только один кандидат больше 0, то выбран этот кандидат. Если сумма кандидата равна 1, верните этот кандидат в качестве ответа. Кандидатами являются:
B (i-1), B (i-1) [2,3,4..N] ++ массив [i], B (i-1) [1,3,4 ..N] ++ array [i] ... B (i-1) [1,2..N-1] ++ array [i]
B (i-2) [2,3, 4..N] ++ array [i], B (i-2) [1,3,4..N] ++ [i] ... B (i-2) [1,2..N -1] ++ массив [I]
...
В (Н) [2,3,4..N] ++ массив [I], В (Н) [1,3, 4..N] ++ array [i] ... B (N) [1,2..N-1] ++ array [i]
Обратите внимание, что для части массива, где числа отрицательные (в случае возрастания сортировки) или положительные (в случае нисходящей сортировки), шаг 3 может быть выполнен немедленно без расчетов.
Выход:
*Main> least 5 "desc" [-1000,-700,-400,-200,-100,-50,10,100,300,600,800,1200]
(10,[-1000,600,300,100,10])
(0.02 secs, 1106836 bytes)
*Main> least 5 "asc" [-1000,-700,-400,-200,-100,-50,10,100,300,600,800,1200]
(50,[300,100,-200,-100,-50])
(0.02 secs, 1097492 bytes)
*Main> main -- 10000 random numbers ranging from -100000 to 100000
(1,[-106,4,-40,74,69])
(1.77 secs, 108964888 bytes)
Код:
import Data.Map (fromList, insert, (!))
import Data.List (minimumBy,tails,sort)
import Control.Monad.Random hiding (fromList)
array = [-1000,-700,-400,-200,-100,-50,10,100,300,600,800,1200]
least n rev arr = comb (fromList listStart) [fst (last listStart) + 1..m]
where
m = length arr
r = if rev == "asc" then False else True
sorted = (if r then reverse else id) (sort arr)
listStart = if null lStart
then [(n,(sum $ take n sorted,take n sorted))]
else lStart
lStart = zip [n..]
. takeWhile (all (if r then (>0) else (<0)) . snd)
. foldr (\a b -> let c = take n (drop a sorted) in (sum c,c) : b) []
$ [0..]
s = fromList (zip [1..] sorted)
comb list [] = list ! m
comb list (i:is)
| fst (list ! (i-1)) == 1 = list ! (i-1)
| otherwise = comb updatedMap is
where updatedMap = insert i bestCandidate list
bestCandidate = comb' (list!(i - 1)) [i - 1,i - 2..n] where
comb' best [] = best
comb' best (j:js)
| fst best == 1 = best
| otherwise =
let s' = map (\x -> (sum x,x))
. (take n . map (take (n - 1)) . tails . cycle)
$ snd (list!j)
t = s!i
candidate = minimumBy compare' (map (add t) s')
in comb' (minimumBy compare' [candidate,best]) js
add x [email protected](a,b) = (x + a,x:b)
compare' [email protected](a',_) [email protected](b',_)
| a' < 1 = if b' < 1 then compare (abs a') (abs b') else GT
| otherwise = if b' < 1 then LT else compare a' b'
rnd :: (RandomGen g) => Rand g Int
rnd = getRandomR (-100000,100000)
main = do
values <- evalRandIO (sequence (replicate (10000) rnd))
putStrLn (show $ least 5 "desc" values)
пожалуйста, вы можете добавить больше информации? Каковы пределы для N, M и чисел? –
Обновлено главное сообщение, спасибо :) –
no Вы не добавили никаких ограничений. Мне нужно знать, каковы максимально допустимые значения N, M и чисел, чтобы я знал, что является необходимой вычислительной сложностью решения. –