问题描述
我目前正在翻Robert Sedgewick's Algorithms本书。在实现优先级队列的书中,使用了Comparable模块。在查看top k frequent elements leetcode problem时,我注意到我的Ruby实现中会出现错误。
def top_k_frequent(nums,k)
ans = []
h = Hash.new(0)
nums.each do |num|
h[num] += 1
end
heap = Heap.new
h.each do |k,v|
heap.insert({k => v})
end
k.times do
a = heap.del_max
ans.push(a.keys[0])
end
ans
end
class Heap
def initialize
@n = 0
@pq = []
end
def insert(v)
@pq[@n += 1] = v
swim(@n)
end
def swim(k)
while k > 1 && less((k / 2).floor,k)
swap((k / 2).floor,k)
k = k/2
end
end
def swap(i,j)
temp = @pq[i]
@pq[i] = @pq[j]
@pq[j] = temp
end
def less(i,j)
@pq[i].values[0] < @pq[j].values[0]
end
def del_max
max = @pq[1]
swap(1,@n)
@n -= 1
@pq[@n + 1] = nil
sink(1)
max
end
def sink(k)
while 2 * k <= @n
j = 2 * k
if !@pq[j + 1].nil?
j += 1 if j > 1 && @pq[j].values[0] < @pq[j + 1].values[0]
end
break if !less(k,j)
swap(k,j)
k = j
end
end
end
上面是Java Priority Queue实现。
解决方法
Ruby的可比运算符为<=>
,它将返回-1
,0
,1
和nil
中的一个(nil
表示无法比较)。
为了比较两个对象,两个都需要实现方法def <=>(other)
。它不在Object
上,因此在任何未实现它或从实现它的类扩展的对象上不可用。例如,数字和字符串确实具有实现。哈希不。
我认为在您的情况下,问题略有不同。
调用queue.insert(my_hash)
时,您希望算法分解my_hash
并以此为基础。取而代之的是,该算法将哈希作为单个原子对象并将其插入。
如果添加以下内容:
class Tuple
attr_accessor :key,:value
def initialize(key,value)
@key = key
@value = value
end
def <=>(other)
return nil unless other.is_a?(Tuple)
value <=> other.value
end
end
然后这将允许您执行以下操作:
hsh = { 1 => 3,2 => 2,3 => 1}
tuples = hsh.map { |k,v| Tuple.new(k,v) }
tuples.each { |tuple| my_heap.insert(tuple) }
您将所有数据都放在堆中。
检索项目时,它将是一个元组,因此您只需调用item.key
和item.value
即可访问数据。