【发布时间】:2014-07-03 19:25:27
【问题描述】:
如果列表中有两个与最后一个相同的相邻值(三个值是一样的),那么它们就会被淘汰,然后递归进行。
例如
(1 5 3 3 2 2 4 3) + 2 => (1 5 3 3 2 2 4 3 2) => (1 5 3 3 4 3) => (1 5 4)
(1 3 3 2) + 2 => (1 3 3 2 2)
我的解决办法是这样的:
一个。扫描列表并获取与列表最后一个相同的两个相同值的第一次出现的位置,如果未找到,则获取 #f。
b.删除这三个值
c。递归调用一个
(define scan ;; list->list (get the position)
(lambda (lst)
(let scan-loop ((lst lst) (n 0))
(cond
[(<= (length lst) 2) #f]
[(and (equal? (car lst) (cadr lst))
(equal? (car lst) (last lst))) n]
[else
(scan-loop (cdr lst) (+ n 1))]))))
(define (Arrange lst k) ; list,k -> list (remove the value)
(remove-k (remove-k (remove-k lst k) k) (- (length lst) 3)))
(define (remove-k lst k)
(let remove-loop ((init lst) (n k) (new '()))
(cond
[(null? init) (error "K is too big for list")]
[(= n 0) (append new (cdr init))]
[else
(remove-loop (cdr init) (- n 1) (append new (list (car init)) ))])))
(define (eliminate lst) ; list ,num -> lst (the main function)
(let ([flag (scan lst)])
(if flag
(eliminate (Arrange lst flag))
lst)))
这可以工作。但是当列表很长时它会变得非常慢。
我有一个测试:
(define lst (build-list 10000 (lambda (x) (random 10))))
(eliminate lst)
在Drracket(6 GB内存,2.3G hz cpu *4)中,根据性能分析,主要的时间成本是:
调用remove-loop,11517101times,花费49283毫秒
调用scan-loop,2450002times,花费121294毫秒
调用Arrange,747times,花费713182毫秒
调用eliminate,748 次,花费130611 毫秒
在运行过程中,我发现只有一个 cpu 几乎 100% 使用(轮流使用)。
这个可以多线程运行吗?
我认为主要问题是我使用的算法效率低下。我认为它可以真正优化。也许使用动态算法,使用一个表来存储发生和每次更新。
该怎么做?
非常感谢。
【问题讨论】:
-
您是否尝试存储(对于每个值?)相邻出现的位置?只能一步一步改变。
-
你能更好地解释你的例子吗(一步一步)?我设法根据数据提出了一些规则,但这似乎与您对消除什么的解释不相符。而且最后3个没有相邻的3个,那为什么要去掉呢?
-
我的错。例子应该是这样的:(1 5 3 3 2 2 4 3) + 2 => (1 5 3 3
2 24 32) => ( 1 53 343) => ( 1 5 4);;; (1 3 3 2) + 2 => (1 3 3 2 2)
标签: algorithm functional-programming scheme racket