我已经完成了关于hackerrank的this问题,我的解决方案通过了大多数测试用例,但对于11个测试用例中的4个来说速度不够快。
我的解决方案如下:
(ns scratch.core
(require [clojure.string :as str :only (split-lines join split)]))
(defn ascii [char]
(int (.charAt (str char) 0)))
(defn process [text]
(let [parts (split-at (int (Math/floor (/ (count text) 2))) text)
left (first parts)
right (if (> (count (last parts)) (count (first parts)))
(rest (last parts))
(last parts))]
(reduce (fn [acc i]
(let [a (ascii (nth left i))
b (ascii (nth (reverse right) i))]
(if (> a b)
(+ acc (- a b))
(+ acc (- b a))))
) 0 (range (count left)))))
(defn print-result [[x & xs]]
(prn x)
(if (seq xs)
(recur xs)))
(let [input (slurp "/Users/paulcowan/Downloads/input10.txt")
inputs (str/split-lines input)
length (read-string (first inputs))
texts (rest inputs)]
(time (print-result (map process texts))))
任何人都可以给我任何关于我应该注意什么的建议,以加快速度吗?
使用递归而不是减少会更快或者这条线很昂贵:
right (if (> (count (last parts)) (count (first parts)))
(rest (last parts))
(last parts))
因为我得了两次计数。
答案 0 :(得分:4)
你在reduce的每次迭代中都冗余地调用reverse:
user=> (let [c [1 2 3]
noisey-reverse #(doto (reverse %) println)]
(reduce (fn [acc e] (conj acc (noisey-reverse c) e))
[]
[:a :b :c]))
(3 2 1)
(3 2 1)
(3 2 1)
[(3 2 1) :a (3 2 1) :b (3 2 1) :c]
反转值可以在包含let中计算,然后只需要计算一次。
此外,由于parts
的定义方式,您每次调用nth
时都会进行线性时间查询。最好将部件放在矢量中并进行索引查找。事实上,您不需要反转部件,并且可以根据矢量的计数进行算术运算,以找到要查找的项目。