- 二分查找,找出列表里是否存在给定的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)
- 二分查找,找出列表里所有的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
感觉写的有点丑。。。
- 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柱子,这就是参数的由来。
- 归并排序
其实我觉得归并排序是最简单的 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
- 牛顿迭代法求开方
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)=x2−c
则该函数的零点为我们要的答案,利用牛顿迭代法找函数零点:
f(x0)+f′(x0)(x−x0)=0
每一次求出x,x将越来越逼近方程的根。
变形上述方程:
x=x0−x20−c2x0
- 汉明数列
对于汉明数集合 X ,有
1)1∈X
2) ∀x∈X,2x,3x,5x∈X
写一个函数,返回这个集合所有元素组成的有序序列。
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..]
- 求
π
我们有计算公式:
π=4(12−13⋅(12)3+15⋅(12)5+⋯)+4(13−13⋅(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))
- 求素数因子
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]
- 矩阵转置
这是我的写法
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])
- 快速幂
-- 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