JS算法之替换空格及从尾到头打印链表

408 阅读2分钟

这是我参与8月更文挑战的第16天,活动详情查看:8月更文挑战

剑指Offer 05.替换空格

替换空格

请实现一个函数,把字符串 s 中的每个空格替换成“%20”。

示例:

 输入:s = “We are happy.”
 输出:“We%20are%20happy.”

限制:0 <= s的长度 <= 10000

题解

解法非常多,利用很多原生api就能解决,如

  • replace / replaceAll
  • encodeURIComponent
  • split / join

或者直接暴力法等,但这些都不是考察等重点。

法一 双指针法

因为JS中字符串无法被修改,一旦给字符串变量重新赋值,就要花费时间和空间去重新新建一个字符串,从而增加了复杂度。

所以我们要采用数组来进行操作,流程如下:

  1. 将字符串转换为数组,然后统计其中的空格数量。
  2. 根据空格数量和原有字符串有效字符长度,计算出刚好存放替换后的字符长度的数组。
  3. 创建两个指针,一个指数组末尾,一个指字符串有效位的末尾,实现原地修改。

其中,数组遍历是从后往前的遍历,避免从前往后,造成字符被修改导致错误。

 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 // 返回的是一个链表,而非数组,这里就不做存数组的操作了
 }

坚持每日一练!前端小萌新一枚,希望能点个哇~