[英]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.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的返回值排序
您可以使用冒泡排序類型算法在一次通過中執行此操作,其中您記下先前值的計數並在找到更多其他數字時交換數字串。
但是 - 作為第一步,您應該執行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.