输入:{5, 13, 6, 5, 13, 7, 8, 6, 5}
输出:{5, 5, 5, 13, 13, 6, 6, 7, 8}
问题是按照频率的降序排列数组中的数字,保留它们出现的顺序。
如果存在平局,例如在13和6之间的示例中,那么输入数组中首先出现的数字将首先出现在输出数组中。
答案 0 :(得分:6)
我想我会这样做:
使用键值数据结构,其中数字本身是键,出现次数和第一次出现索引是值。
现在遍历所有数字。如果数字尚未知晓(在数据结构中),请添加它,记住当前索引以及1作为计数。否则,递增计数。
现在按出现次数(减少)和出现次数(增加)对数据结构内容进行排序,然后输出结果(使用出现次数重复该次数)。
使用的处理空间< = N,根据数据结构和字典使用的时间可能约为O(N log N)
答案 1 :(得分:3)
我可以想到两个解决方案:
这很容易实现,在最坏的情况下使用线性(O(N))附加内存并且需要O(N log N)时间。
这样做只需一次通过,但我想不出任何优于其他解决方案的优势。它仍然需要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);
}