zoukankan      html  css  js  c++  java
  • 算法练习笔记(四)

    10.25

    字符串中的第一个唯一字符

    给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。

    示例:

    s = "leetcode"
    返回 0

    s = "loveleetcode"
    返回 2

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/first-unique-character-in-a-string

    思路

    ①使用数组两次遍历,第一次统计每个字符出现的次数,第二次找到次数仅为1的字符,返回其索引

    ②使用s.indexOf(s[i])===s.lastIndexOf(s[i]) 找到首次出现和最后一次出现的索引相同的字符,即为不重复的字符

    代码

    //第一种
    var firstUniqChar = function(s){
    	// 长度为26的数组,存放字符的出现次数
    	const arr = new Array(26).fill(0)
    	//统计字符出现的次数
    	for(let i=0;i<s.length;i++){
    		arr[s[i].charCodeAt(0)-97]++
    	}
    	//再次遍历,找到唯一字符
    	for(let i=0;i<s.length;i++){
    		if(arr[s[i].charCodeAt(0)-97]===1){
    			return i
    		}
    	}
    	return -1
    }
    
    //第二种
    var firstUniqChar = function(s){
        for(let i=0;i<s.length;i++){
            if(s.indexOf(s[i])===s.lastIndexOf(s[i])){
                return i
            }
        }
        return -1
    }
    

    对称二叉树

    给定一个二叉树,检查它是否是镜像对称的。

    image-20211025161842757

    代码

    //使用递归
    const isMirror = function(left,right){
    	//左子树右子树都为空
    	if(!left&&!right){
    		return true
    	}
    	//只有一边为空
    	if(!left||!right){
    		return false
    	}
    	//递归比较左子树和右子树
    	if(left.val === right.val){
    		return isMirror(left.left,right.right)&&isMirror(left.right,right.left)
    	}
    	return false
    }
    var isSymmetric = function(root){
        return isMirror(root.left,root.right)
    }
    

    10.26

    二叉树的最大深度

    给定一个二叉树,找出其最大深度。

    二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

    说明: 叶子节点是指没有子节点的节点。

    示例:
    给定二叉树 [3,9,20,null,null,15,7],

       3
      / 
      9  20
        /  
       15   7
    返回它的最大深度 3 。
    

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/maximum-depth-of-binary-tree

    思路

    ①递归:一个树的最大深度 = 根节点的高度(即1)+ 左右子树的最大深度中的较大者。

    ②BFS

    代码:

    //递归
    var maxDepth = function(root){
    	if(!root) return 0
    	//计算左子树的深度
    	let left = maxDepth(root.left)
    	//计算右子树的深度
    	let right = maxDepth(root.right)
    	return Math.max(left,right)+1
    }
    //BFS
    var maxDepth = function(root){
        if(!root) return 0
        const queue = []
        queue.push(root)
        let maxDepth = 1
        while(queue.length){
            //记录当前层的节点个数
    		let len = queue.length
            //逐个让当前层的节点出列
            for(let i=0;i<len;i++){
                const cur = queue.shift()
                //左右子节点入列
                if(cur.left) queue.push(cur.left)
                if(cur.right) queue.push(cur.right)
            }
            // 当前层所有节点已经出列,如果队列不为空,说明有下一层节点,maxDepth+1
            if(queue.length) maxDepth++
        }
        return maxDepth
    }
    

    二叉树的层序遍历

    给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。

    示例:
    二叉树:[3,9,20,null,null,15,7],

       3
      / 
      9  20
        /  
       15   7
    返回其层序遍历结果:
    

    [
    [3],
    [9,20],
    [15,7]
    ]

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal

    代码:

    var levelOrder = function(root) {
        //初始化结果数组
        const res = []
        //处理边界条件
        if(!root) return res
        const queue = []
        queue.push(root)
        //队列不为空时,反复执行以下逻辑
        while(queue.length){
            //记录当前层的节点个数
            let len = queue.length
            //cur存储当前层的节点
            let cur = []
            for(let i=0;i<len;i++){
                //取出队列的头部元素
                const top = queue.shift()
                //将头部元素的值推入cur数组
                cur.push(top.val)
                //如果当前结点有左右孩子,则推入下一层级
                if(top.left) queue.push(top.left)
                if(top.right) queue.push(top.right)
            }
            //将cur推入结果数组
            res.push(cur)
        }
        //返回结果数组
        return res
    };
    

    10.27

    二叉树的锯齿形层序遍历

    给定一个二叉树,返回其节点值的锯齿形层序遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。

    例如:
    给定二叉树 [3,9,20,null,null,15,7],

      3
     / 
      9  20
        /  
       15   7
    返回锯齿形层序遍历如下:
    

    [
    [3],
    [20,9],
    [15,7]
    ]

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/binary-tree-zigzag-level-order-traversal

    思路:在层序遍历的基础上,设置标志判断奇数层和偶数层的添加方法

    代码:

    //BFS
    var zigzagLevelOrder = function(root){
    	//结果数组
    	const res = []
    	if(!root)return res
    	const queue = []
    	queue.push(root)
    	//初始化标志
    	let isRightOrder = false
    	while(queue.length){
    		const len = queue.length
    		//保存该层节点
    		const cur = []
    		for(let i=0;i<len;i++){
    			let top = queue.shift()
    			if(isRightOrder){
    				cur.unshift(top.val)
    			}else{
    				cur.push(top.val)
    			}
    			//记录该节点的左右节点
    			if(top.left){
    				queue.push(top.left)
    			}
    			if(top.right){
    				queue.push(top.right)
    			}
    		}
    		res.push(cur)
    		isRightOrder = !isRightOrder
    	}
    	return res
    }
    //递归DFS
    var zigzagLevelOrder = function(root){
        const arr = []
        function loop(node,level){
            if(!node)return
            if(!arr[level])arr[level] = []
            if(level%2){//实现从右往左
                arr[level].unshift(node.val)
            }else{//实现从左往右
                arr[level].push(node.val)
            }
            //进入下一层
            loop(node.left,level+1)
            loop(node.right,level+1)
        }
        loop(root,0)
        return arr
    }
    

    从前序与中序遍历序列构造二叉树

    给定一棵树的前序遍历 preorder 与中序遍历 inorder。请构造二叉树并返回其根节点。

    示例 1:

    Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
    Output: [3,9,20,null,null,15,7]

    示例 2:

    Input: preorder = [-1], inorder = [-1]
    Output: [-1]

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal

    代码

    来源:https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/solution/jian-dan-gan-jing-de-xie-fa-by-dokomzhu-25oi/

    定位出根节点,划分出左右子树,然后 递归 构建左右子树

    var buildTree = function(preorder,inorder){
    	if(!preorder.length||!inorder.length) return null
    	let node = new ListNode(preorder[0])
    	let index = inorder.indexOf(preorder.shift())
    	node.left = buildTree(preorder,inorder.slice(0,index))
    	node.right = buildTree(preorder,inorder.slice(index+1))
    	return nodex
    }
    

    10.28

    填充每个节点的下一个右侧节点指针

    给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:

    struct Node {
    int val;
    Node *left;
    Node *right;
    Node *next;
    }
    填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。

    初始状态下,所有 next 指针都被设置为 NULL。

    进阶:

    你只能使用常量级额外空间。
    使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。

    image-20211028122613166

    思路

    由题意可知,每个结点root,它的左孩子root.left的next指向右孩子root.right(有左孩子肯定有右孩子),而它的右孩子root.right指向父节点root的邻居左孩子,即root.nextl.left(只要root.next存在)。

    代码:

    var connect = function(root){
    	if(!root)return null
    	//存在左孩子
    	if(root.left){
    		root.left.next = root.right
    		//存在邻居
    		if(root.next){
    			root.right.next = root.next.left
    		}
    	}
    	connect(root.left)
    	connect(root.right)
    	return root
    }
    

    二叉搜索树中第K小的元素

    给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 个最小元素(从 1 开始计数)。

    image-20211028121944037

    image-20211028122004457

    思路

    二叉搜索树的中序遍历是有序的,利用二叉搜索树的特点进行遍历,从左的节点开始计数,将第 k 个节点的值返回。

    代码:

    var kthSmallest = function(root, k) {
    	let ans
    	function inorderTraverse(root){
    		if(!root||k<0)return null
    		inorderTraverse(root.left)
    		if(--k == 0){
    			ans = root.val
    		}
    		inorderTraverse(root.right)
    	}
    	inorderTraverse(root)
    	return ans
    }
    

    10.29

    二叉树的最近公共祖先

    给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

    百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

    image-20211029120830550

    image-20211029121106850

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree

    思路

    参考https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/solution/jsersi-lu-hao-li-jie-by-hyj8/

    代码

    var lowestCommonAncestor = function(root,p,q){
    	if(!root||p==root||q==root)return root
    	const left = lowestCommonAncestor(root.left,p,q)
    	const right = lowestCommonAncestor(root.right,p,q)
    	if(left&&right){
    		return root
    	}
    	if(!left){
    		return right
    	}
    	return left
    }
    

    3的幂

    给定一个整数,写一个函数来判断它是否是 3 的幂次方。如果是,返回 true ;否则,返回 false 。

    整数 n 是 3 的幂次方需满足:存在整数 x 使得 n == 3x

    示例 1:

    输入:n = 27
    输出:true

    示例 2:

    输入:n = 0
    输出:false

    示例 3:

    输入:n = 9
    输出:true

    示例 4:

    输入:n = 45
    输出:false

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/power-of-three

    代码:

    //递归
    var isPowerOfThree = function(n){
    	if(n == 1)return true
    	if(n == 0||n%3!==0)return false
    	return isPowerOfThree(n/3)
    }
    //循环
    var isPowerOfThree = function(n){
        while(n>1){
            n /= 3
        }
        return n==1
    }
    
  • 相关阅读:
    截取url中最后斜杆的文件名
    html span从上往下,从左往右排序
    浪漫源码记录
    微信小程序TypeError: Cannot read property 'elem' of undefined
    tomcat8 性能优化
    Bandicam神奇使用法
    DataStage 七、在DS中使用配置文件分配资源
    DataStage 六、安装和部署集群环境
    DataStage 错误集(持续更新)
    DataStage 三、配置ODBC
  • 原文地址:https://www.cnblogs.com/Small-Windmill/p/15459197.html
Copyright © 2011-2022 走看看