JS算法之合并两个排序的链表及树的子结构

680 阅读2分钟

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

合并两个排序的链表

剑指Offer 25.合并两个排序的链表

难度:简单

输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。

示例1:

 输入:1->2->4, 1->3->4
 输出:1->1->2->3->4->4

限制:0 <= 链表长度 <= 1000

题解

法一 递归法

递归 分治剪枝:返回有效期望链表项

 /**
  * Definition for singly-linked list.
  * function ListNode(val) {
  *     this.val = val;
  *     this.next = null;
  * }
  */
 /**
  * @param {ListNode} l1
  * @param {ListNode} l2
  * @return {ListNode}
  */
 var mergeTwoLists = function(l1, l2) {
   if(l1 === null) return l2;
   if(l2 === null) return l1;
   if(l1.val < l2.val){
     l1.next = mergeTwoLists(l1.next,l2);
     return l1;
   }else{
     l2.next = mergeTwoLists(l1,l2.next);
     return l2;
   }
 };

时间复杂度:O(m+n),空间复杂度O(m+n)

法二 迭代法

设置哨兵节点preNode,流程如下

  • l1和l2均没遍历完:

    • 如果l1.val > l2.val,当前node的next指向l2,移动l2指针。
    • 否则,当前node的next指向l1,移动l1指针。
    • 移动node指针
    • 继续循环
  • 否则,结束循环:

    • 如果l1未遍历完,node的next指向l1
    • 如果l2未遍历完,node的next指向l2
 var mergeTwoLists = function(l1,l2){
   if(!l1){
     return l2;
   }else if(!l2){
     return l1;
   }
   let preNode = new ListNode(-1);
   let node = preNode;
   while(l1 && l2){
     if(l1.val > l2.val){
       node.next = l2;
       l2 = l2.next;
     }else{
       node.next = l1;
       l1 = l1.next;
     }
     node = node.next;
   }
   if(l1){
     node.next = l1;
   }else if(l2){
     node.next = l2;
   }
   return preNode.next;
 }
  • 时间复杂度O(m+n),m和n分别为两链表长度
  • 空间复杂度O(1)

树的子结构

剑指Offer 26.树的子结构

难度:中等

输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)。

B是A的子结构,即A中有出现和B相同的结构和节点值。

例如:

给定的树A:

      3
     / \
    4   5
   / \
  1   2

给定的树B:

    4 
   /
  1

返回true,因为B与A的一个子树拥有相同的结构和节点值。

示例1:

 输入:A = [1,2,3], B = [3,1]
 输出:false

示例2:

 输入:A = [3,4,5,1,2], B = [4,1]
 输出:true

限制:0 <= 节点个数 <= 10000

题解

递归法

步骤:

  • 判断A和B是否为空,为空则返回false
  • 比较当前节点值或者A的左右子树的值相对于B的值(A的根节点和B的根节点不同的情况)
  • 递归比较左右节点的值,直到遍历完B树。
 /**
  * Definition for a binary tree node.
  * function TreeNode(val) {
  *     this.val = val;
  *     this.left = this.right = null;
  * }
  */
 ​
 /**
  * @param {TreeNode} A
  * @param {TreeNode} B
  * @return {boolean}
  */
 var isSubStructure = function(A,B){
   // 约定空树不是任意一个树的子结构
   if(!A || !B){
     return false;
   }
   return isSameTree(A,B) || isSubStructure(A.left,B) || isSubStructure(A.right,B)
 };
 ​
 var isSameTree = function(A,B){
   // B子树是空子树 ok
   if(!B){
     return true;
   }
   // A子树是空子树且B非空,不ok
   if(!A){
     return false;
   }
   // 当前节点的值不相等,不ok
   if(A.val !== B.val){
     return false;
   }
   // 递归考察左子树、右子树
   return isSameTree(A.left,B.left) && isSameTree(A.right,B.right);
 }
  • 时间复杂度:最坏情况下为O(m*n),其中m为A树的节点数,n为B树的节点数
  • 空间复杂度:最坏情况下就是一条直的树枝没有分叉,为B的高度n,即O(n)

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