1816. 截断句子
题目描述
句子 是一个单词列表,列表中的单词之间用单个空格隔开,且不存在前导或尾随空格。每个单词仅由大小写英文字母组成(不含标点符号)。
- 例如,
"Hello World"、"HELLO"和"hello world hello world"都是句子。
给你一个句子 s 和一个整数 k ,请你将 s 截断 ,使截断后的句子仅含 前 k 个单词。返回 截断 s 后得到的句子。
示例 1:
输入:s = "Hello how are you Contestant", k = 4 输出:"Hello how are you" 解释: s 中的单词为 ["Hello", "how" "are", "you", "Contestant"] 前 4 个单词为 ["Hello", "how", "are", "you"] 因此,应当返回 "Hello how are you"
示例 2:
输入:s = "What is the solution to this problem", k = 4 输出:"What is the solution" 解释: s 中的单词为 ["What", "is" "the", "solution", "to", "this", "problem"] 前 4 个单词为 ["What", "is", "the", "solution"] 因此,应当返回 "What is the solution"
示例 3:
输入:s = "chopper is not a tanuki", k = 5 输出:"chopper is not a tanuki"
提示:
1 <= s.length <= 500k的取值范围是[1, s 中单词的数目]s仅由大小写英文字母和空格组成s中的单词之间由单个空格隔开- 不存在前导或尾随空格
解法
方法一:字符串分割
思考
要从句子中保留前 \(k\) 个单词。按空格切分再拼接,逻辑直接,额外需要存放单词列表的空间。
语言自带的 \(\textit{split}\) 已按空白切开单词,取前 \(k\) 个再以空格连接即可,实现与题意一一对应。
将句子按空格拆成单词,再取前 \(k\) 个单词拼接回去。
时间复杂度 \(O(n)\),空间复杂度 \(O(n)\)。其中 \(n\) 为字符串 \(s\) 的长度。
1 2 3 | |
方法二:模拟
思考
方法一产生了中间数组。若只关心截断位置,从左扫描并在遇到空格时将 \(k\) 减一,\(k\) 变为 \(0\) 时当前下标即为第 \(k\) 个单词之后的空格,返回其前缀;若扫描结束 \(k\) 仍为正,则整句不足 \(k\) 个单词,原串即为答案。额外空间可降为 \(O(1)\)。
我们从前往后遍历字符串 \(s\),对于当前遍历到的字符 \(s[i]\),如果 \(s[i]\) 是空格,那么 \(k\) 自减 \(1\),当 \(k\) 为 \(0\) 时,说明已经截取了 \(k\) 个单词,截取字符串 \(s[0..i)\) 返回即可。
遍历结束,返回 \(s\) 即可。
时间复杂度 \(O(n)\),其中 \(n\) 为字符串 \(s\) 的长度。忽略答案的空间消耗,空间复杂度 \(O(1)\)。
1 2 3 4 5 6 7 | |
1 2 3 4 5 6 7 8 9 10 | |
1 2 3 4 5 6 7 8 9 10 11 | |
1 2 3 4 5 6 7 8 9 10 11 | |
1 2 3 4 5 6 7 8 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 | |