[路飞_js算法实现:最长公共子序列 买卖股票的最佳时机 使用最小花费爬楼梯 翻转二叉树]

541 阅读3分钟

最长公共子序列

问题描述: 给定两个字符串 text1text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。

  • 例如,"ace""abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。

两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。(by leetcode 剑指 Offer II 095)

示例 :

输入:text1 = "abcde", text2 = "ace" 
输出:3  
解释:最长公共子序列是 "ace" ,它的长度为 3

思路-动态规划:

① 横轴是text1,纵轴是text2,指针在横轴和纵轴上往后移动,当纵轴与横轴值相等,那么就加上斜轴当前位置向上一个位置的值+1,若不相等,则取上方或者左边相对较大的值。

② 由于要处理前面的值,为了方便,我们给格子第一行和第一列都填上0.

/**
 * @param {string} text1
 * @param {string} text2
 * @return {number}
 */
var longestCommonSubsequence = function(text1, text2) {
  let len1=text1.length,len2=text2.length;
    let d=new Array(len1+1).fill(0).map(item=>new Array(len2+1).fill(0));
    for(let i=1;i<=len1;i++){
        for(let j=1;j<=len2;j++){
            if(text1.charAt(i-1)==text2.charAt(j-1)){
                d[i][j]=d[i-1][j-1]+1
            }else{
                d[i][j]=Math.max(d[i-1][j],d[i][j-1])
            }
        }
    }
    return d[len1][len2]
};

买卖股票的最佳时机

问题描述: 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。(by leetcode 121

示例 :

输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

思路:

后面的值减前面的值的最大差值便是我们要输出的值,从前往后走的时候:

1.我们需要计算差值,与之前最大的差值比较。

2.找到最小值,用于后面计算差值。

3.遍历到最后,返回最大的差值。

/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function(arr) {
    let minPrice=arr[0];
    let max=0;
    for(let i=0;i<arr.length;i++){
        if(arr[i]<minPrice){
            minPrice=arr[i]
        }
        if(arr[i]-minPrice>max){
            max=arr[i]-minPrice
        }
        
    }
    return max
}

使用最小花费爬楼梯

问题描述: 数组的每个下标作为一个阶梯,第 i 个阶梯对应着一个非负数的体力花费值 cost[i](下标从 0 开始)。

每当你爬上一个阶梯你都要花费对应的体力值,一旦支付了相应的体力值,你就可以选择向上爬一个阶梯或者爬两个阶梯。

请你找出达到楼层顶部的最低花费。在开始时,你可以选择从下标为 0 或 1 的元素作为初始阶梯。(by leetcode746

示例 :

输入:cost = [10, 15, 20]
输出:15
解释:最低花费是从 cost[1] 开始,然后走两步即可到阶梯顶,一共花费 15

思路-动态规划:

计算到达每一个节点需要的体力值(这里需要比较大小来确定从前一个还是前两个位置跳过来)。问题就变成了求最后一个节点的后一个节点需要的体力值。

/**
 * @param {number[]} cost
 * @return {number}
 */
var minCostClimbingStairs = function(cost) {
let arr=[0,0]//往第一个节点跳需要的体力值
for(let i=2;i<=cost.length;i++){
    arr[i]=Math.min(arr[i-2]+cost[i-2],arr[i-1]+cost[i-1])
}
    return arr[arr.length-1]
};

翻转二叉树

问题描述: 翻转一棵二叉树。(by leetcode 226)

示例:

输入:

     4
   /   \
  2     7
 / \   / \
1   3 6   9

输出:

     4
   /   \
  7     2
 / \   / \
9   6 3   1

思路:

采用递归的方式,交换左右子树(子树是交换好的)

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {TreeNode}
 */
var invertTree = function(root) {
    if(root==null) return root;
    let left=invertTree(root.left);
    let right=invertTree(root.right);
    root.left=right;
    root.right=left;
    return root;
 
};