Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 如何重新排列数组,使每个元素都比相邻元素大/小_Arrays_Algorithm_Sorting - Fatal编程技术网

Arrays 如何重新排列数组,使每个元素都比相邻元素大/小

Arrays 如何重新排列数组,使每个元素都比相邻元素大/小,arrays,algorithm,sorting,Arrays,Algorithm,Sorting,例如,如果数字为: 30, 12, 49, 6, 10, 50, 13 阵列将是: [10, 6, 30, 12, 49, 13, 50] 如你所见: 6小于10和30,并且 49大于12和13,依此类推 这些数字都是不同的、真实的。我需要最有效的算法。假设数字都是不同的,最简单的方法可能是对数字进行排序,然后交错排序列表的前半部分和后半部分。这将保证高/低/高/低/高/低/。。。。你需要的图案 此算法是O(n log n),对于大多数目的来说,它应该足够有效,并且可能受益于标准库中优化

例如,如果数字为:

30, 12, 49, 6, 10, 50, 13
阵列将是:

[10, 6, 30, 12, 49, 13, 50]
如你所见:

  • 6小于10和30,并且
  • 49大于12和13,依此类推

这些数字都是不同的、真实的。我需要最有效的算法。

假设数字都是不同的,最简单的方法可能是对数字进行排序,然后交错排序列表的前半部分和后半部分。这将保证高/低/高/低/高/低/。。。。你需要的图案

此算法是
O(n log n)
,对于大多数目的来说,它应该足够有效,并且可能受益于标准库中优化的排序例程


如果数字不明显,则可能没有解决方案(例如,如果数字都相等)

我对复杂性不太了解,但我的想法如下

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]
哈斯克尔代码:

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
这可以在O(n)中完成:

  • 查找O(n)中的中值(说明见
  • 将每个大于中值的元素放在奇数位置,将每个较小的元素放在偶数位置

  • 当然,这是假设所有元素都是不同的,否则有时它会失败。

    有人把这个问题作为一个傻瓜贴了出来,但那里的解决方案比这里接受的解决方案好,所以我想我应该把它贴在这里

    基本上,关键是每三个数字,它必须保持
    ac
    你看序列,把最大的数字换到中间。然后你增加2到下一个序列,如
    ac
    ,然后做同样的事情


    从技术上讲,该解决方案仍然像已接受的解决方案一样在O(n)中运行,但它是一个更好的O(n)而且它更简单,因为中值算法很难实现。希望任何喜欢这个问题的人至少都能看到这个解决方案,如果有人感兴趣,我可以发布代码。

    你需要所有的解决方案还是只需要第一个?如果算法能生成所有的解决方案,那就太好了。但是算法必须时间效率最高。我觉得计算“所有解决方案”可能会有
    O(n!)
    复杂性…最好的解决方案不在这里检查一下,我认为这将是最好的方法[23]是一半[12]是另一半。所以[21 3 2]实际上是将两半交错。为了记录在案,@mikera说他的解决方案是针对不同的数字…取决于你先放哪一半。我会尝试想出一个反例。不需要完全排序。使用快速选择(中位数)算法,你可以在
    O(n)中找到中位数元素
    并将数组分成大小,然后可以交错,
    O(n)
    。是的,出于实际目的,快速的
    O(n log(n))
    比慢速的
    O(n)
    @a Webb更好-很好的一点,我同意不需要完全排序。不过如果您的语言有一个像样的排序实现(可能?)它可能会击败手动中值分区实现,并且使用.YMMV时会更简单/更少出错。这似乎不起作用。例如,对于
    [3,4,0,1,2]
    它返回
    [1,0,2,4,3]
    这是无效的,因为
    2
    大于
    0
    ,但小于
    4
    。在这种情况下,一个有效的解决方案是,例如
    [0,4,1,3,2]
    。使用查找。@hammar这里有一件有趣的事情:我更改了一行,如下所示:
    prop_correct(Distinct xs)=odd(length xs)| valid(reseat xs)
    我得到了:
    +++好的,通过了100次测试。
    等一下!我们找不到O(n)中的中值通过选择,我们可以找到中位数的中位数,它不一定是中位数。它不在数组长度的50%,只是大于30%和小于70%。@Peggy:请阅读整篇维基百科文章,即使我们可以始终选择最小部分为30%的pivot,这对于quickselect为O(n)就足够了在最坏的情况下。是的,你是对的。在找到中间值的中间值后,我们可以通过找到第(n/2)个最小元素来再次找到中间值。(找到第k个最小元素iin O(n))。对不起
    *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]