这是我参与8月更文挑战的第16天,活动详情查看:8月更文挑战
剑指Offer 05.替换空格
替换空格
请实现一个函数,把字符串 s 中的每个空格替换成“%20”。
示例:
输入:s = “We are happy.”
输出:“We%20are%20happy.”
限制:0 <= s的长度 <= 10000
题解
解法非常多,利用很多原生api就能解决,如
- replace / replaceAll
- encodeURIComponent
- split / join
或者直接暴力法等,但这些都不是考察等重点。
法一 双指针法
因为JS中字符串无法被修改,一旦给字符串变量重新赋值,就要花费时间和空间去重新新建一个字符串,从而增加了复杂度。
所以我们要采用数组来进行操作,流程如下:
- 将字符串转换为数组,然后统计其中的空格数量。
- 根据空格数量和原有字符串有效字符长度,计算出刚好存放替换后的字符长度的数组。
- 创建两个指针,一个指数组末尾,一个指字符串有效位的末尾,实现原地修改。
其中,数组遍历是从后往前的遍历,避免从前往后,造成字符被修改导致错误。
var replaceSpace = function(s){
s = s.split(""); // 用于把字符串转为字符串数组
let oldLen = s.length;
let spaceCount = 0;
for(let i = 0; i < oldLen; i++){
if(s[i] === ' ') spaceCount++;
}
s.length += spaceCount * 2;
for(let i = oldLen - 1, j = s.length - 1; i >= 0; i--, j--){
if(s[i] !== ' ') s[j] = s[i];
else {
s[j-2] = '%';
s[j-1] = '2';
s[j] = '0';
j -= 2;
}
}
return s.join(''); // 用于把数组中的所有元素放入一个字符串
}
- 时间复杂度:O(n)
- 空间复杂度:O(n)
法二 遍历添加
新建一个字符串去操作,时间复杂度和空间复杂度均为O(n),这里就不展开讨论了。
从尾到头打印链表
剑指Offer 06.从尾到头打印链表
输入一个链表的头节点,从尾到头反过来返回每个节点的值。(用数组返回)。
示例:
输入:head = [1,3,2]
输出:[2,3,1]
限制: 0 <= 链表长度 <= 10000
题解
法一 常规解法
遍历链表、将每个元素从数组头部插入、实现倒序输出。
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {number[]}
*/
var reversePrint = function(head){
let nums = [];
let node = head;
while(node !== null){
nums.unshift(node.val);
node = node.next;
}
return nums;
}
法二 递归法
递归思路:递归本身与栈的后进先出的原理一致,通过递归从最后一个结果开始保存到数组中,实现倒序打印。
这种方法需要注意是否会因为链表过长导致栈溢出。
var reversePrint = function(head){
let nums = []
const visit = function(head){
if(head!==null){
visit(head.next)
nums.push(head.val)
}
};
visit(head) // 首次进入
return nums
}
法三 反转链表法
先将链表反转,后对反转的链表进行遍历输出
var reversePrint = function(head){
if(head === null || head.next === null) return head;
let p = head.next;
head.next = null;
let tmp = null;
while(p!==null){
tmp = p.next
p.next = head
head = p
p = tmp
}
return head // 返回的是一个链表,而非数组,这里就不做存数组的操作了
}
坚持每日一练!前端小萌新一枚,希望能点个赞哇~