我构建了一个过程,它应该接受一个参数,一个带有数字作为条目的向量,然后返回最低值。
(define min-number
(lambda (vec)
(define looping
(lambda (i v-min)
(if (= i (vector-length vec))
v-min
(looping (+ i 1) (min v-min (vector-ref vec i))))))
(looping 1 (vector-ref vec 0))
)
)
现在我想构造一个返回向量的第二个最小值的过程。这是应该在不将向量转换为列表的情况下完成的事情。我怎么能这样做的想法?我无法摆脱“列表思维”。我的头对我说“使用汽车”,“使用cdr”等等在这种特殊情况下不起作用。因此,任何想法将不胜感激。嗯,我想我已经涵盖了所有内容,如果有什么不清楚,请告诉我。
谢谢:)
答案 0 :(得分:2)
另一种方法,类似于Óscar的答案,两者都是O(n)。这适用于任何序列,包括列表和向量!
(define (second-lowest seq)
(define-values (_ x)
(for/fold ((a #f) (b #f))
((x seq))
(cond ((< x (or a (add1 x))) (values x a))
((< x (or b (add1 x))) (values a x))
(else (values a b)))))
x)
答案 1 :(得分:1)
如果您被允许使用内置函数,这里有一个简单的方法:找到最小值,然后查找不那个最小值的下一个最小值。这就是我的意思:
(define min-number
(lambda (vec)
(let ((min-val (vector-argmin identity vec)))
(vector-argmin
(lambda (x) (if (equal? x min-val) +inf.0 x))
vec))))
例如:
(min-number '#(5 4 1 2 3))
=> 2
答案 2 :(得分:1)
通过快速选择算法很好地解决了向量的第k个最小元素。
(define (quickselect A k)
(define pivot (list-ref A (random (length A))))
(define A1 (filter (curry > pivot) A))
(define A2 (filter (curry < pivot) A))
(cond
[(<= k (length A1)) (quickselect A1 k)]
[(> k (- (length A) (length A2))) (quickselect A2 (- k (- (length A) (length A2))))]
[else pivot]))
(quickselect '(9 8 7 6 5 0 1 2 3 4) 2) ; => 1
来自http://rosettacode.org/wiki/Quickselect_algorithm#Racket的代码
答案 3 :(得分:0)
以下是vector-select
的两个版本,它们在向量v
中找到第k个最小元素。这意味着(vector-select v 1)
找到向量中的第二个最小元素。 vector-select
和vector-select!
之间的区别在于后者可能会更改向量中元素的顺序。两个过程的预期时间为O(n)
,其中n
是向量的长度。
#lang racket
; vector-ref and vector-set! is used so often, so introduce shorter notation
(define-syntax-rule (vref v i) (vector-ref v i))
(define-syntax-rule (vset! v i e) (vector-set! v i e))
; vector-select : vector index -> number
; find the kth largest element of v
; (where 0 <= k < n )
(define (vector-select v k)
(define n (vector-length v))
(unless (<= 0 k (- n 1))
(error 'vector-select "expected a number between 0 and the length of the vector"))
(subvector-select! (vector-copy v) k 0 n))
; vector-select! : vector index -> number
; find the kth largest element of v
; (where 0 <= k < n )
; side effect: the order of the elements may change
(define (vector-select! v k)
(define n (vector-length v))
(unless (<= 0 k (- n 1))
(error 'vector-select! "expected a number between 0 and the length of the vector"))
(subvector-select! v k 0 n))
; subvector-select : vector index index index -> number
; find the kth largest element of the elements v[s],v[s+1],...,v[t-1].
; assumption: s<t (i.e. the subvector is non-empty)
(define (subvector-select! v k s t)
(define n (- t s)) ; length of subvector
(cond
[(= n 1) (unless (= k 0) (error "Error 1"))
(vref v s)]
[else (define r (randomized-partion! v s t)) ; v[r] is a pivot
(define l (- r s)) ; number of elements left of pivot (in subvector)
(cond
[(= k l) (vref v r)] ; found it!
[(< k l) (subvector-select! v k s r)] ; the element is left of the pivot
[else (subvector-select! v (- k l) r t)])])) ; the element is right of the pivot
; randomized-partion! : vector index index -> index
; Pick a random index between s and t, then partion the elements
; in the subvector v[s],v[s+1],...,v[t-1] using v[r] as pivot.
; I.e. move elements smaller than the pivot to appear before the pivot
; and move elements larger than the pivot to appear after the pivot.
; Finally return the index of the pivot.
(define (randomized-partion! v s t)
;; Helper
; swap! : index index -> void
; swap elements with index i and j
(define (swap! i j)
(define vi (vref v i))
(vset! v i (vref v j))
(vset! v j vi))
;; Main
(define r (+ s (random (- t s)))) ; pick random pivot index in subvector
(define p (vref v r)) ; the pivot value
(swap! (- t 1) r) ; place the pivot as the last value in the subvector
(define i s) ; invariant: all elements before v[i] are <= pivot
(for ([j (in-range s (- t 1))]) ; loop through all elements (except the pivot)
(when (<= (vref v j) p) ; if the element is non-greater than the pivot
(swap! i j) ; move it to the front of the subvector
(set! i (+ i 1)))) ; and update i to the next available slot
(swap! i (- t 1))
i) ; finally put the pivot in place