我是Scheme新手,我正在使用Dr.Racket试图找到列表的中位数。
如果列表L的长度是奇数,则函数median返回列表中的中值元素。如果L的长度是偶数,则函数median返回0.示例
(median ‘(1)) returns 1
(median ‘(1 2)) returns 0
(median ‘(1 2 3)) returns 2
(median ‘( 1 2 3 4) returns 0
我只能使用:
我们不允许使用两个功能。它应该类似(define median (lambda (<list L followed by parameters of your choice initially set to zero>) (cond )))
,它应该只有一个递归函数。所有辅助参数必须是数字(不是列表),并且初始值应设置为零。例如,如果L是‘(1 2 3 4)
并决定使用一个额外的辅助参数,则应将中位数称为(median '(1 2 3 4) 0 )
。
中位数将列表分成两组,长度相等。这是中位数的定义属性:如果中位数之前的元素数等于后面的元素数,那么元素就是中位数。因此,为了找到中值,对于每个列表元素,需要计算在给定元素之前的元素的数量和成功它的元素的数量。如果这两个数字相同,则找到中位数。问题表示涉及以下变量: - 列表L; - 目标元素(潜在中位数),比如说“目标”; - 一个计数器,用于表示目标前面元素的数量,比如count1 - 一个计数器,用于计算目标后面元素的数量,比如count2,我想出了这样的结果:
(define median(lambda (list target count1 count2 loop )
(cond
((null? list)(if (= count1 count2) target 0))
((if (= loop 1)
(if (= target (median (cdr list) target count1 (+ 1 count2) 1 ))
target
(median (cdr list) (car list) (+ count1 1) 0 1 )
))))))
但我被困在这里......任何人都可以帮忙吗?
答案 0 :(得分:0)
如果我很好地阅读了你的约束,那么应该这样做:
(define median
(lambda (lst pass cnt1 cnt2)
(cond
; pass 0 = initial call - call pass 1 then pass 2
((= pass 0) (median lst 2 (median lst 1 0 0) 0))
; pass 1 = determine the position of the median (-1 or n//2)
((= pass 1) (if (null? lst)
(if (= cnt1 cnt2) -1 (sub1 cnt1))
(median (cdr lst) 1 (add1 cnt2) cnt1)))
; pass 2 = find element
(else (cond
((eqv? cnt1 -1) 0)
((eqv? cnt1 0) (car lst))
(else (median (cdr lst) 2 (sub1 cnt1) 0)))))))
它基本上有3个传球,有些参数对于不同的传球有不同的含义,所以你当然不会在现实世界中写下这样的东西。
测试:
> (median '(1) 0 0 0)
1
> (median '(1 2) 0 0 0)
0
> (median '(1 2 3) 0 0 0)
2
> (median '(1 2 3 4) 0 0 0)
0
> (median '(1 2 3 4 5) 0 0 0)
3