[路飞]_js算法实现:前 K 个高频元素 二叉树的直径 最长回文串 最长递增子序列 排序数组

245 阅读1分钟

前 K 个高频元素

问题描述: 给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。(by leetcode 347)

示例 :

输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]

思路-桶排序:

① 首先遍历得出每个元素出现的次数,

② 然后建立数组,数组下标是次数,值对应元素值。(其实是把桶放到指定下标位置,桶里面的元素个数不一定)

③ 从数组最后的下标开始找元素,找前k个有元素值的元素返回。

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var topKFrequent = function(nums, k) {
    let map=new Map;
   // 第一步
    for(let i=0;i<nums.length;i++){
        if(map.get(nums[i])){
            map.set(nums[i],map.get(nums[i])+1)
        }else{
            map.set(nums[i],1)
        }
    }
    //第二步
    let arr=[];
    for(let [key,value] of map){
        if(arr[value]&&arr[value].length){
            arr[value].push(key)//对应位置已有桶,直接放值
        }else{
             arr[value]=[key]//摆放桶,并放值
        }
    }
    //第三步
    let newarr=[],count=0;
    for(let i=arr.length;i>0&&count<k;i--){
     if(arr[i]){//保证桶里有值
       newarr=newarr.concat(arr[i]);
       count+=arr[i].length 
        }
    }
    return newarr;
};

二叉树的直径

问题描述: 给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。(by leetcode 534)

示例 :

给定二叉树    
      1
     / \
    2   3
   / \     
  4   5    
返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。

思路:

最长深度优先(这个概念后面补充)

用递归,递归函数返回的是每个节点中,左右节点中最长的那颗子树的直径。

算出每个节点左右子树相加最长的路径是多少,作为节点值。从最叶节点开始算起,往上的节点值就是叶节点的值相加。

/**
 * 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 {number}
 */
var diameterOfBinaryTree = function(root) {
    var ans=0;
    var depth=function(root){
  if(root==null) return 0;
   let l=depth(root.left)//当前节点左子树最长直径
   let r=depth(root.right)//当前节点右子树最长直径
    ans=Math.max(ans,l+r);//经过当前节点的最长直径跟之前的最大值比较。
   return Math.max(l,r)+1//该节点向上链接父节点,所以直径加1,max中取出来的值代表要连接那颗子树                                             
}
    depth(root);
    return ans
};

最长回文串

问题描述: 给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。(by leetcode 409

在构造过程中,请注意区分大小写。比如 "Aa" 不能当做一个回文字符串。

注意: 假设字符串的长度不会超过 1010。

示例 1:

输入:
"abccccdd"
输出:
7
解释:
我们可以构造的最长的回文串是"dccaccd", 它的长度是 7

思路:

用Set管理,偶数的删除,奇数最多一个。(找到回文串的特点即可知道)

/**
 * @param {string} s
 * @return {number}
 */
var longestPalindrome = function(str) {
    let set=new Set()
    let arr=str.split("");
    console.log(arr)
    let num=0;
    for(let i=0;i<arr.length;i++){
        if(set.has(arr[i])){
            set.delete(arr[i]);
            num+=2;
        }else{
            set.add(arr[i])
        }
    }
    if(set.size){
        num++
    }
    return num
};

最长递增子序列

问题描述: 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。(by leetcode

示例 1:

输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4

思路:

动态规划 直接上代码吧,注释先放到代码里面哦~

/**
 * @param {number[]} nums
 * @return {number}
 */
var lengthOfLIS = function(nums) {
   if(!nums.length){
        return nums
    }
    let long=[];//用来存储对应位置到之前的最长递增
    let ins=1;
    for(let i=0;i<nums.length;i++){
       long[i]=1;//默认经过本身,所以是1
        for(let j=0;j<i;j++){
            if(nums[j]<nums[i]){
                long[i]=Math.max(long[i],long[j]+1)//如果当前值比之前某个值大,说明可以排在那个值后面,所以要看那个值的long高(加1是因为要加上当前值)还是本身的高
            }
        }
        ins=Math.max(ins,long[i])//往后循环找最大值,也就是最长递增序列长度
    }
    return ins
};

排序数组

问题描述: 给你一个整数数组 nums,请你将该数组升序排列。(by leetcode 912

示例 1:

输入:nums = [5,2,3,1]
输出:[1,2,3,5]

思路:

采用二路归并排序 采用分治的思想 先排小的,再排大的,也是用递归的形式

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortArray = function(nums) {
partSort(nums,0,nums.length-1)
return nums
};
 var partSort=function(num,l,r){
    if(l>=r)return false;
    let mid=Math.floor((r+l)/2);
    partSort(num,l,mid)//排左边 同时修改了内部的值
    partSort(num,mid+1,r)//排左边
    let i=l,j=mid+1;//增加两个指针,用于找到最小值
    let temp=[];
    while(i<=mid&&j<=r){
        if(num[i]<=num[j]){
         temp.push(num[i])
          i++
        }else{
         temp.push(num[j])
          j++
        }
    }
    while(i<=mid){
        temp.push(num[i])
        i++;
    }
    while(j<=r){
        temp.push(num[j])
        j++;
    }
     //用排好的临时数组修改本身的值
   for (let i = 0; i < temp.length; ++i) {
            num[i + l] = temp[i];
   }
}