Vector 求向量的第二小值
我已经解释了一个过程,它应该以一个参数,一个以数字为条目的向量,然后返回最小值Vector 求向量的第二小值,vector,scheme,racket,minimum,Vector,Scheme,Racket,Minimum,我已经解释了一个过程,它应该以一个参数,一个以数字为条目的向量,然后返回最小值 (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)))))) (loopin
(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等等,在这种特殊情况下不起作用。因此,任何想法都将不胜感激。嗯,我想我涵盖了一切,如果有不清楚的地方,请告诉我
谢谢:如果允许使用内置函数,这里有一个简单的方法:找到最小值,然后查找下一个不是最小值的最小值。这就是我的意思:
(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
快速选择算法很好地解决了寻找向量第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
代码来自另一种方法,类似于Óscar的答案,两者都是开启的。这一个适用于任何序列,包括列表和向量
(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)
下面是vector select的两个版本,它查找向量v中的第k个最小元素。这意味着vector select v 1将查找向量中第二个最小的元素。向量选择和向量选择之间的区别!后者可能会改变向量中元素的顺序。这两个过程的预期时间均为On,其中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
谢谢,我想这样就行了:为什么这么多人在做手术我想这是你的罗塞塔代码。@ChrisJester Young你是对的-这个版本不是一个有效代码的例子。我从头开始写了一个向量select。看看新的答案。