[Haskell] 一些简单题

  1. 二分查找,找出列表里是否存在给定的x
    显然,列表必须是有序的(这就包括了元素是可比较的,也就是都属于Ord类型类)。
binarySearch :: (Ord a) => a -> [a] -> Bool
binarySearch x list | x < mid = binarySearch x front
                    | x > mid = binarySearch x behind
                    | x == mid = True
                    | otherwise = False
                    where (front, mid : behind) = (splitAt (div (length list) 2) list)
  1. 二分查找,找出列表里所有的x
binarySearch :: (Ord a) => a -> [a] -> [a]
binarySearch x list | x < mid = binarySearch x front
                    | x > mid = binarySearch x behind
                    | x == mid = concat [[x], binarySearch x front, binarySearch x behind]
                    | otherwise = []
                    where (front, mid : behind) = splitAt (div (length list) 2) list

感觉写的有点丑。。。

  1. Hanoi塔
hanoi :: (Int, Int, Int, Int) -> [(Int, Int)]
-- hanoi (num, from, to, via) -> [(from, to)]

hanoi (num, from, to, via) = hanoi (num - 1, from, via, to) + [(from, to)] + hanoi (num - 1, via, to, from)
-- hanoi num = 2 * hanoi (num - 1) + 1

hanoi塔很简单,hanoi函数表示最小的num个金片,从from柱子顺序不变地移动到to柱子,via柱子用来中转的移动情况。由于是最小的num个金片,所以3个柱子的已有金片并不会导致金片无法放置的情况,所以可以忽略三个柱子原有的其他金片。然后如果要移动n个金片,就要先把n-1个金片先移开(即移动到via柱上),再移动第n个金片到to柱子上,再将之前的n-1个金片再移动到to柱子上,为了满足小的金片一定在上的条件。

那么对于n-1个金片,第一次移动,从from柱子移动到目前的via柱子,经过to柱子。第二次移动,从via柱子移动到to柱子,经过from柱子,这就是参数的由来。

  1. 归并排序
    其实我觉得归并排序是最简单的 O(nlogn) 排序算法了。。。
merge x [] = x
merge [] x = x
merge (a:la) (b:lb) | a < b = a : merge la (b:lb)
                    | otherwise = b : merge (a:la) lb

mergeSort list | length list <= 1 = list
               | otherwise = merge (mergeSort l1) (mergeSort l2)
               where (l1, l2) = splitAt (div (length list) 2) list
  1. 牛顿迭代法求开方
    https://www.zhihu.com/question/20690553
    这里讲的挺不错的。
-- squareRoot iteration root
squareRoot 0 c = c
squareRoot n c = x0 - (x0 ^ 2 - c) / (2 * x0) where x0 = squareRoot (n - 1) c

令函数

f(x)=x2c

则该函数的零点为我们要的答案,利用牛顿迭代法找函数零点:
f(x0)+f(x0)(xx0)=0

每一次求出x,x将越来越逼近方程的根。
变形上述方程:
x=x0x20c2x0

  1. 汉明数列
    对于汉明数集合 X ,有
    1) 1X
    2) xX,2x,3x,5xX
    写一个函数,返回这个集合所有元素组成的有序序列。
divide x y
 | mod x y == 0 = divide (div x y) y
 | otherwise = x
ham = filter (\x -> divide (divide (divide x 2) 3) 5 == 1) [1..]
  1. π
    我们有计算公式:
    π=4(1213(12)3+15(12)5+)+4(1313(13)3+15(13)5+)

    那么两个无限项数列可以用下面的函数表示
series base = [(1 / (fromIntegral x)) * (base ^ fromIntegral x) * (-1) ^ div (fromIntegral x) 2 | x <- [1,3..]]

其中base为被乘方的数,在这里取 12 13
然后就知道了:

num = 2000000 -- compute times.
mypi = (sum $ take num $ series (1/2)) * 4 + 4 * (sum $ take num $ series (1/3))
  1. 求素数因子
primeFactors n =
  case factors of
    [] -> [n]
    _  -> factors ++ primeFactors (n `div` head factors)
  where factors = take 1 $ filter (\x -> (n `mod` x) == 0) [2 .. floor $ sqrt $ fromIntegral n]
  1. 矩阵转置
    这是我的写法
transpose :: [[a]] -> [[a]]
transpose [xs] = [[x]|x<-xs]
transpose (xs:xss) = zipWith (++) (transpose [xs]) (transpose xss)

下面是书上的写法

transpose :: [[a]] -> [[a]]
transpose [] = []
transpose ([]:xss) = transpose xss
transpose ((x:xs) : xss) = (x : [h | (h:_) <- xss]) : transpose (xs : [t | (_:t) <- xss])
  1. 快速幂
-- quickPower (*) 2 8 = 256
quickPower f a n
 | n == 1 = a
 | odd n = let m = quickPower f a (div n 2) in f (f m m) a
 | otherwise = let m = quickPower f a (div n 2) in f m m
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值