如何改进这个列表算法?

时间:2014-05-15 11:18:23

标签: algorithm functional-programming scheme racket

如果列表中有两个相邻的值与最后一个相同(三个值),则给出一个数字列表(字符或其他任何内容)和另一个随机数字(字符或与列表相同的类型)是相同的),然后它们将被淘汰,然后递归地进行 例如
(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。

湾删除那三个值

℃。递归调用

(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-loop11517101次,费用为49283毫秒 致电scan-loop2450002次,费用为121294毫秒 致电Arrange747次,费用为713182毫秒 致电eliminate748次,费用为130611毫秒

在跑步过程中,我发现只有一个cpu几乎100%被使用(轮流) 这可以由多线程运行吗?

我认为主要问题是我使用的算法效率低下。我认为它可以真正优化。也许使用动态算法,每次使用表来存储事件并更新 怎么做?

非常感谢。

1 个答案:

答案 0 :(得分:1)

不要在Dr Racket中测量结果,因为IDE的开销非常高。始终从shell执行时间密集型计算。

这是我的算法,对于10,000个元素的列表执行时间不到半秒(对于算法的9.5分钟):

(define (remn lst)
  (if (null? lst)
      lst
      (let* ((rlst (reverse lst)) (last (car rlst)))
        (let loop ((left null) (curn 0) (rght (reverse (cdr rlst))))
          (if (null? rght)
              (append (reverse left) (list last))
              (let ((e (car rght)))
                (if (equal? e last)
                    (if (= curn 1)
                        (remn (append (reverse (cdr left)) (cdr rght)))
                        (loop (cons e left) (add1 curn) (cdr rght)))
                    (loop (cons e left) 0 (cdr rght)))))))))

示例:

> (remn '(1 5 3 3 2 2 4 3 2))
'(1 5 4)
> (remn '(1 3 3 2 2))
'(1 3 3 2 2)
> (remn '(1 1 3 3 3 3 3 1))
'(3 3)