如何按每个数字的频率降序排列数组?

时间:2010-03-25 16:07:50

标签: algorithm arrays

输入:{5, 13, 6, 5, 13, 7, 8, 6, 5}

输出:{5, 5, 5, 13, 13, 6, 6, 7, 8}

问题是按照频率的降序排列数组中的数字,保留它们出现的顺序。

如果存在平局,例如在13和6之间的示例中,那么输入数组中首先出现的数字将首先出现在输出数组中。

7 个答案:

答案 0 :(得分:6)

我想我会这样做:

使用键值数据结构,其中数字本身是键,出现次数和第一次出现索引是值。

现在遍历所有数字。如果数字尚未知晓(在数据结构中),请添加它,记住当前索引以及1作为计数。否则,递增计数。

现在按出现次数(减少)和出现次数(增加)对数据结构内容进行排序,然后输出结果(使用出现次数重复该次数)。

使用的处理空间< = N,根据数据结构和字典使用的时间可能约为O(N log N)

答案 1 :(得分:3)

我可以想到两个解决方案:

首先计算频率并存储第一个索引,然后根据

进行排序

这很容易实现,在最坏的情况下使用线性(O(N))附加内存并且需要O(N log N)时间。

使用某种priority queue一次性完成所有操作,其中“priority”是频率计数(当您通过输入时更改),以及第一次出现断开关系的索引

这样做只需一次通过,但我想不出任何优于其他解决方案的优势。它仍然需要O(N)额外的内存,并且还需要O(N log N)时间。此外,它需要更复杂的数据结构。

答案 2 :(得分:2)

Python2.7 Python3.1

>>> from collections import Counter
>>> L=[5, 13, 6, 5, 13, 7, 8, 6, 5]
>>> c=Counter(L)
>>> def keyfunc(x):
...     return (-c.get(x),L.index(x))
... 
>>> sorted(L,key=keyfunc)
[5, 5, 5, 13, 13, 6, 6, 7, 8]

Python2.6

>>> from collections import defaultdict
>>> L=[5, 13, 6, 5, 13, 7, 8, 6, 5]
>>> c=defaultdict(int)
>>> for x in L:
...     c[x]+=1
... 
>>> def keyfunc(x):
...     return (-c.get(x),L.index(x))
... 
>>> sorted(L,key=keyfunc)
[5, 5, 5, 13, 13, 6, 6, 7, 8]

以下是不使用任何库函数的版本(奇怪的约束)

>>> L=[5, 13, 6, 5, 13, 7, 8, 6, 5]
>>> c={}
>>> for x in L:
...     c[x]=c.setdefault(x,0)+1
... 
>>> def keyfunc(x):
...     return (-c.get(x),L.index(x))
... 
>>> sorted(L,key=keyfunc)
[5, 5, 5, 13, 13, 6, 6, 7, 8]

在每种情况下,keyfunc用于控制排序的排序

keyfunc(5) returns (-3,0)
keyfunc(6) returns (-2,2)
keyfunc(7) returns (-1,5)
keyfunc(8) returns (-1,6)
keyfunc(13) returns (-2,1)

列表项根据keyfunc的返回值

排序

答案 3 :(得分:1)

您可以使用冒泡排序类型算法在一次通过中执行此操作,其中您记下先前值的计数并在找到更多其他数字时交换数字串。

但是 - 作为第一步,你应该做一个2pass解决方案,使用std :: map / pair来存储数字,或者如果你被告知事先使用一个简单的数组范围。

答案 4 :(得分:1)

C#。它采用最明显的方法:按频率和顺序排序。

输出:5 5 5 13 13 6 6 7 8。 空间:O(n)。时间:O(n log n)。

class Program
{
    class FreqAndOrdinal
    {
        public int Frequency;
        public int Ordinal;
        public FreqAndOrdinal(int freq, int ord)
        {
            this.Frequency = freq;
            this.Ordinal = ord;
        }
    }

    static int Compare(FreqAndOrdinal x, FreqAndOrdinal y)
    {
        int result = y.Frequency.CompareTo(x.Frequency);
        return result == 0 ? x.Ordinal.CompareTo(y.Ordinal) : result;
    }

    static void Main(string[] args)
    {
        int[] nums = new int[] { 5, 13, 6, 5, 13, 7, 8, 6, 5 };
        var freqLookup = new Dictionary<int, FreqAndOrdinal>(nums.Length);
        for (int i = 0; i < nums.Length; i++)
        {
            FreqAndOrdinal tmp;
            if (freqLookup.TryGetValue(nums[i], out tmp))
                ++tmp.Frequency;
            else
                freqLookup[nums[i]] = new FreqAndOrdinal(1, i);
        }

        Array.Sort(nums, (x,y) => Compare(freqLookup[x], freqLookup[y]));

        for (int i = 0; i < nums.Length; i++)
        {
            Console.Write(" {0}", nums[i]);
        }
        Console.ReadKey();
    }
}

答案 5 :(得分:0)

对数组进行排序,并在x,y的排序函数中排序:按count(x)与count(y)排序。如果它们相同,则按索引(x)与索引(y)

排序

在python中:

input = [5, 13, 6, 5, 13, 7, 8, 6, 5]
orig = list(input)

def cmp(x, y):
    if (orig.count(y) - orig.count(x) != 0):
        return orig.count(y) - orig.count(x)
    return orig.index(x) - orig.index(y)   

input.sort(cmp) 
print input

为了提高效率,请在对数组进行排序之前预先计算计数和索引。

答案 6 :(得分:0)

private static void sortByFrequency(int[] a)
{
    Map<Integer, Element> map = new HashMap<Integer, Element>();
    for(int i=0; i<a.length; i++)
    {
        if(map.get(a[i]) == null)
        {
            map.put(a[i], new Element(i));
        }
        else
        {
            Element e = map.get(a[i]);
            e.frequency++;
        }
    }

    Set<Integer> set = map.keySet();
    TreeSet<Element> treeSet = new TreeSet<Element>();
    for(int i : set)
    {
        treeSet.add(map.get(i));
    }

    for(Element e : treeSet)
    {
        for(int i=0; i<e.frequency;i++)
        {
            System.out.println(a[e.index]);
        }
    }
}

private static class Element implements Comparable<Element>
{
    private final int index;
    private int frequency;

    Element(int index)
    {
        this.index = index;
        this.frequency = 1;
    }

    @Override
    public int compareTo(Element o)
    {
        int k = o.frequency - this.frequency;
        if(k != 0) return k;
        else
        {
            return this.index - o.index;
        }
    }
}

public static void main(String[] args)
{
    int[] a = {5, 13, 6, 5, 13, 7, 8, 6, 5};
    sortByFrequency(a);
}