leetcode 算法合集

102 二叉树的层序遍历(*)

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

/*
 * @param {TreeNode} root
 * @return {number[][]}
 */
 var levelOrder = function(root) {
	let arr = []
	if(!root)return arr
	const q = []
	q.push(root)
	while(q.length!=0){
		const currentLevelSize = q.length;
		arr.push([])
		for(let i = 1;i<=currentLevelSize;i++){
			const node = q.shift()
			arr[arr.length-1].push(node.val)
			if(node.left) q.push(node.left)
			if(node.right)q.push(node.right)
		 }
	 }
	return arr
};

114 二叉树展开为链表(*)

给你二叉树的根结点 root ,请你将它展开为一个单链表:
展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
展开后的单链表应该与二叉树 先序遍历 顺序相同。

/**
 * @param {TreeNode} root
 * @return {void} Do not return anything, modify root in-place instead.
 */
var flatten = function(root) {
	const list = []
	const stack = []
	let node = root
	while(node!==null||stack.length){
		while(node!=null){
			list.push(node)
			stack.push(node)
			node = node.left
		}
		node = stack.pop();
		node = node .right
	}
	const size = list.length
	for(let i=1;i<size;i++){
		const prev = list[i-1],curr=list[i]
		prev.left = null
		prev.right= curr
	}
}

121 买卖股票的最佳时机(*)

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function(prices) {
	let maxProfit = 0 //最大收益
	let minPrice = prices[0] //最小价格
	for(let i=1;i<prices.length;i++){
		if(prices[i]<minPrice){
			minPrice = prices[i]
		}else{
			maxProfit = Math.max(prices[i]-minPrice,maxProfit)
		}
	}
	return maxProfit
};

122 买卖股票的最佳时机II(*)

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。

在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。返回 你能获得的 最大 利润 。

示例 1:

输入:prices = [7,1,5,3,6,4]
输出:7
解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。
     随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3 。
     总利润为 4 + 3 = 7 。
示例 2:

输入:prices = [1,2,3,4,5]
输出:4
解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。
     总利润为 4 。
示例 3:

输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 交易无法获得正利润,所以不参与交易可以获得最大利润,最大利润为 0
/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function(prices) {
	var len = prices.length
	const dp = new Array(len).fill(0).map(v=>new Array(2).fill(0))
	dp[0][0] = 0
	dp[0][1] = -prices[0]
	for(let i=1;i<len;i++){
		dp[i][0] = Math.max(dp[i-1][0],dp[i-1][1]+prices[i])
		dp[i][1] = Math.max(dp[i-1][1],de[i-1][0]-prices[i])
	}
	return dp[len-1][0]
};

146 LRU 缓存(*)

请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。
实现 LRUCache 类:
LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。
函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。

/**
 * @param {number} capacity 设置容量
 */
var LRUCache = function(capacity) {
	this.capacity = capacity
	this.queue = new Map()
};

/** 
 * @param {number} key
 * @return {number}
 */
LRUCache.prototype.get = function(key) {
	if(this.queue.has(key)){
		const value = this.queue.get(key)
		this.queue.delete(key)
		this.queue.set(key,value)
		return value
	}
	return -1
};

/** 
 * @param {number} key 
 * @param {number} value
 * @return {void}
 */
LRUCache.prototype.put = function(key, value) {
	if(this.queue.has(key)){
		this.queue.delete(key)
	}
	this.queue.set(key,value)
	if(this.queue.size>this.capacity){
		if(this.queue.size){
			this.queue.delete(this.queue.keys().next().value)
		}
	}
};

236 叉树的最近公共祖先(*)

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

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @param {TreeNode} p
 * @param {TreeNode} q
 * @return {TreeNode}
 */
var lowestCommonAncestor = function(root, p, q) {
  if(root==null||root==p||root==q)return root
	let left = lowestCommonAncestor(root.left,p,q)
	let right = lowestCommonAncestor(root.right,p,q)
	//都不为空,说明做右子树都有目标结点,则公共祖先就是本身
	if(left!=null&&right!=null)return root 
	//如果发现了目标节点,则继续向上标记为该目标节点
    return left==null?right:left  
};

面试题 16.17. 连续数列(*)

给定一个整数数组,找出总和最大的连续数列,并返回总和。

示例:

输入: [-2,1,-3,4,-1,2,1,-5,4]
输出: 6

解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
    let pre = 0, maxAns = nums[0]
    nums.forEach(x=>{
        pre = Math.max(pre+x,x)
        maxAns = Math.max(maxAns,pre)
    })
    return maxAns
};

面试题 17.01. 不用加号的加法(*)

设计一个函数把两个数字相加。不得使用 + 或者其他算术运算符。

示例:

输入: a = 1, b = 1
输出: 2
/**
 * @param {number} a
 * @param {number} b
 * @return {number}
 */
var add = function(a, b) {
    while (b != 0) {
        const carry = (a & b) << 1;
        a = a ^ b;
        b = carry;
    }
    return a;
};

面试题 17.04. 消失的数字

数组nums包含从0到n的所有整数,但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗?

注意:本题相对书上原题稍作改动

示例 1:

输入:[3,0,1]
输出:2

示例 2:

输入:[9,6,4,2,3,5,7,0,1]
输出:8
/**
 * @param {number[]} nums
 * @return {number}
 */
var missingNumber = function(nums) {
    const set = new Set();
    const n = nums.length;
    for (let i = 0; i < n; i++) {
        set.add(nums[i]);
    }
    let missing = -1;
    for (let i = 0; i <= n; i++) {
        if (!set.has(i)) {
            missing = i;
            break;
        }
    }
    return missing;
};

面试题 17.10. 主要元素

数组中占比超过一半的元素称之为主要元素。给你一个 整数 数组,找出其中的主要元素。若没有,返回 -1 。请设计时间复杂度为 O(N) 、空间复杂度为 O(1) 的解决方案。

示例 1:

输入:[1,2,5,9,5,9,5,5,5]
输出:5

示例 2:

输入:[3,2]
输出:-1

示例 3:

输入:[2,2,1,1,1,2,2]
输出:2

答案:

let find = -1;
let count = 0;
for (const num of nums) {
   // 若数量为0,找到的元素设置为当前元素
  if (count === 0) {
      find = num;
   }
  if (num === find) {
      count++;
   } else {
      count--;
  }
}
count = 0;
for (const num of nums) {
  if (num === find) {
      count++;
   }
}
return count * 2 > nums.length ? find : -1;

面试题 61. 扑克牌中的顺子

从若干副扑克牌中随机抽 5 张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。

示例 1:

输入: [1,2,3,4,5]
输出: True

示例 2:

输入: [0,0,1,2,5]
输出: True

答案:

let set = new Set();
let max = 0,min = 14;
for(let a of nums){
     if(a==0)continue;
     max = Math.max(a,max)
     min = Math.min(a,min)
     if(set.has(a))return false
     set.add(a)
}
return max-min<5
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值