簡體   English   中英

如何按每個數字的頻率降序排列數組?

[英]How to arrange an array in decreasing order of frequency of each number?

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

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

問題是按照頻率的降序排列數組中的數字,保留它們出現的順序。

如果存在平局,例如在13和6之間的示例中,那么輸入數組中首先出現的數字將首先出現在輸出數組中。

我想我會這樣做:

使用鍵值數據結構,其中數字本身是鍵,出現次數和第一次出現索引是值。

現在遍歷所有數字。 如果數字尚未知曉(在數據結構中),請添加它,記住當前索引以及1作為計數。 否則,遞增計數。

現在按出現次數(減少)和出現次數(增加)對數據結構內容進行排序,並輸出結果(使用出現次數重復該次數)。

使用的處理空間<= N,根據數據結構和字典使用的時間可能約為O(N log N)

我可以想到兩個解決方案:

首先計算頻率並存儲第一個索引,然后根據它進行排序

這很容易實現,在最壞的情況下使用線性(O(N))附加存儲器並且需要O(N log N)時間。

使用某種優先級隊列一次性完成所有操作,其中“優先級”是頻率計數(當您通過輸入時更改),以及第一次發生斷開關系的索引

這樣做只需一次通過,但我無法想到與其他解決方案相比的任何優勢。 它仍然需要O(N)額外的內存,並且還需要O(N log N)時間。 此外,它需要更復雜的數據結構。

Python2.7Python3.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的返回值排序

您可以使用冒泡排序類型算法在一次通過中執行此操作,其中您記下先前值的計數並在找到更多其他數字時交換數字串。

但是 - 作為第一步,您應該執行2pass解決方案,使用std :: map / pair來存儲數字,或者如果您被告知事先使用一個簡單的數組。

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();
    }
}
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);
}

對數組進行排序,並在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

為了提高效率,請在排序數組之前預先計算計數和索引。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM