P21 - 在指定位置插入元素

2026-09-07 00:00    #Haskell   #99题   #列表  

P21 - 在指定位置插入元素

Insert an element at a given position into a list

官方模块:Problems.P21 核心函数:insertAt


← P20 删除第 k 个元素 | P22 生成整数范围 →


题目描述

把元素插入列表的第 nn 个位置。题目使用从 1 开始的位置编号,因此位置 1 表示插到列表最前面。

函数签名

1insertAt :: a -> [a] -> Int -> [a]

实现

方法一:splitAt(推荐)

1insertAt :: a -> [a] -> Int -> [a]
2insertAt x xs n = front ++ x : back
3  where
4    (front, back) = splitAt (n - 1) xs

在位置 nn 插入,等价于在前 n1n-1 个元素之后插入。splitAt 一步切出前后两段,再把新元素接在中间。

++ 的右侧是 x : back(不是 [x] ++ back),所以只复制前缀,不产生额外 : 操作。若位置超过列表长度,splitAtback = [],新元素自然追加到末尾。

方法二:递归

1insertAt :: a -> [a] -> Int -> [a]
2insertAt x []     _ = [x]
3insertAt x xs     1 = x : xs
4insertAt x (y:ys) n = y : insertAt x ys (n - 1)

三种情况分别处理:

这是最符合 Haskell 列表递归直觉的写法。

方法三:zip + takeWhile

1insertAt :: a -> [a] -> Int -> [a]
2insertAt x xs n = take (n - 1) xs ++ x : drop (n - 1) xs

不依赖 splitAt,直接 take + drop。当 n 很大时 take 取到整个列表,drop 返回 [],新元素加在末尾。

方法对比

方法核心操作特点
splitAtsplitAt一次切分,语义清晰
递归: + 递归纯模式匹配,教学友好
take/droptake + drop + ++工具函数组合

测试

1>>> insertAt 'X' "abcd" 2
2"aXbcd"
3>>> insertAt 0 [1,2,3] 1
4[0,1,2,3]
5>>> insertAt 4 [1,2,3] 99
6[1,2,3,4]

参考