How to rearrange an array in such a way that each element is greater/smaller than its neighbours

前端 未结 4 1660
孤独总比滥情好
孤独总比滥情好 2020-12-29 10:50

For example, if the numbers are:

30, 12, 49, 6, 10, 50, 13

The array will be:

[10, 6, 30, 12, 49, 13, 50]
<
4条回答
  •  渐次进展
    2020-12-29 11:09

    I'm not too knowledgeable about complexity, but here's my idea.

    For even length lists:
    
    (For our odd length example, 
     put 30 aside to make the list even) 
    
    1. Split the list into chunks of 2    => [[12,49],[6,10],[50,13]]
    2. Sort each chunk                    => [[12,49],[6,10],[13,50]]
    3. Reverse-sort the chunks by 
       comparing the last element of 
       one to the first element of 
       the second                         => [[12,49],[13,50],[6,10]]
    
    For odd length lists:
    4. Place the removed first element in 
       the first appropriate position     => [30,12,49,13,50,6,10]
    

    Haskell code:

    import Data.List (sortBy)
    import Data.List.Split (chunksOf)
    
    rearrange :: [Int] -> [Int]
    rearrange xs
      | even (length xs) = rearrangeEven xs
      | null (drop 1 xs) = xs
      | otherwise        = place (head xs) (rearrangeEven (tail xs))
     where place x (y1:y2:ys) 
             | (x < y1 && y1 > y2) || (x > y1 && y1 < y2) = (x:y1:y2:ys)
             | otherwise                                  = place' x (y1:y2:ys)
           place' x (y1:y2:ys) 
             | (x < y1 && x < y2) || (x > y1 && x > y2) = (y1:x:y2:ys)
             | otherwise                                = y1 : (place' x (y2:ys))
           rearrangeEven = concat 
                         . sortBy (\a b -> compare (head b) (last a)) 
                         . map sort
                         . chunksOf 2
    

    Output:

    *Main> rearrange [30,12,49,6,10,50,13]
    [30,12,49,13,50,6,10]
    
    *Main> rearrange [1,2,3,4]
    [3,4,1,2]
    

提交回复
热议问题