我需要优化此代码。有任何建议让它变得更快,请告诉我。我没有特定的数量,我希望它更快,任何建议都会有所帮助。就复杂性而言,我希望将其保持在O(n ^ 2)
以下我想知道是否尝试将我正在使用的数组转换为set或hash,因为这样更快?在复杂性方面,这可以让我运行多快?
我认为主要的问题可能是我使用的ruby组合函数运行速度很慢,有没有人确切知道这个ruby函数的复杂性?有更快的替代方案吗?
这段代码的重点基本上是找到与所有其他点的最短组合距离的单点,即(每个人最方便的朋友家)。这里有一些额外的代码,它有一些调试/打印功能。
class Point
attr_accessor :x, :y, :distance, :done, :count
def initialize(x,y)
@x = x
@y = y
@distance = 0
@closestPoint = []
@done = false
@count = 0
end
end
class Edge
attr_accessor :edge1, :edge2, :weight
def initialize(edge1,edge2,weight)
@edge1 = edge1
@edge2 = edge2
@weight = weight
end
end
class AdjacencyList
attr_accessor :name, :minSumList, :current
def initialize(name)
@name = name
@minSumList = []
@current = nil
@vList = []
@edgeList = []
end
def addVertex(vertex)
@vList.push(vertex)
end
def generateEdges2
minSumNode = nil
current = nil
last = nil
@vList.combination(2) { |vertex1, vertex2|
distance = distance2points(vertex1,vertex2)
edge = Edge.new(vertex1,vertex2,distance)
if (current == nil)
current = vertex1
minSumNode = vertex1
end
vertex1.distance += distance
vertex2.distance += distance
vertex1.count += 1
vertex2.count += 1
if (vertex1.count == @vList.length-1)
vertex1.done = true
elsif (vertex2.count == @vList.length-1)
vertex2.done = true
end
if ((vertex1.distance < minSumNode.distance) && (vertex1.done == true))
minSumNode = vertex1
end
#@edgeList.push(edge)
}
return minSumNode.distance
end
def generateEdges
@vList.combination(2) { |vertex1, vertex2|
distance = distance2points(vertex1,vertex2)
@edgeList.push(Edge.new(vertex1,vertex2,distance))
}
end
def printEdges
@edgeList.each {|edge| puts "(#{edge.edge1.x},#{edge.edge1.y}) <=> (#{edge.edge2.x},#{edge.edge2.y}) weight: #{edge.weight}"}
end
def printDistances
@vList.each {|v| puts "(#{v.x},#{v.y} distance = #{v.distance})"}
end
end
def distance2points(point1,point2)
xdistance = (point1.x - point2.x).abs
ydistance = (point1.y - point2.y).abs
total_raw = xdistance + ydistance
return totaldistance = total_raw - [xdistance,ydistance].min
end
#pointtest1 = Point.new(0,1)
#pointtest2 = Point.new(2,5)
#pointtest3 = Point.new(3,1)
#pointtest4 = Point.new(4,0)
graph = AdjacencyList.new("graph1")
gets
while (line = gets)
graph.addVertex(Point.new(line.split[0].to_i,line.split[1].to_i))
end
#graph.addVertex(pointtest1)
#graph.addVertex(pointtest2)
#graph.addVertex(pointtest3)
#graph.addVertex(pointtest4)
puts graph.generateEdges2
#graph.printEdges
#graph.printDistances
答案 0 :(得分:2)
尝试执行此操作,然后发布更多代码:
ruby -rprofile your_script your_args
这将在探查器下运行脚本,并生成一个包含结果的漂亮表。如果您在此处发布,则更有可能获得更好的帮助。此外,您将更准确地了解消耗CPU周期的因素。
答案 1 :(得分:1)
集合基本上是哈希值,散列优于数组的优点是O(1)查找操作。由于您只是遍历整个数组,如果只是用散列替换数组,散列将不会提供任何速度提升。
你真正的问题是你的算法的运行时间是O(n ^ 2),因为给定一组n个点它将必须执行n ^ 2个操作,因为你将每个点与其他每个点匹配点。
使用哈希缓存值可以稍微改善一下。例如,假设您想要点“a”和点“b”之间的距离。您可以使用存储@distances
的哈希@distances["a,b"] = 52
(当然,您必须明智地知道要使用什么作为密钥)。基本上只是尝试在任何地方删除冗余操作。
也就是说,最大的速度提升将来自更智能的算法,但我现在无法想到一些适用的东西。
答案 2 :(得分:0)
有很多人都知道的东西,它不会让你付出任何代价。
当您试图猜测如何使代码更快,或者在互联网上搜索某种类型的分析器时,只需在调试器下运行该程序并在它缓慢时中断它。
多次这样做,每次都要仔细记录它正在做什么以及为什么。
越慢,问题就越明显。