牛客面试高频算法题js(实现二叉树先序,中序和后序遍历、最小的K个数、求二叉树的层序遍历、寻找第K大、链表中的节点每k个一组翻转)

NC45 实现二叉树先序,中序和后序遍历

描述

给定一棵二叉树,分别按照二叉树先序,中序和后序打印所有的节点。

数据范围:0 \le n \le 10000≤n≤1000,树上每个节点的val值满足 0 \le val \le 1000≤val≤100

要求:空间复杂度 O(n)O(n),时间复杂度 O(n)O(n)

样例解释:

在这里插入图片描述

示例1

输入:

{1,2,3}

返回值:

[[1,2,3],[2,1,3],[2,3,1]]

说明:

如题面图  

示例2

输入:

{}

返回值:

[[],[],[]]

备注:

n \leq 10^6n≤106

代码:

/*
 * function TreeNode(x) {
 *   this.val = x;
 *   this.left = null;
 *   this.right = null;
 * }
 */

/**
 * 
 * @param root TreeNode类 the root of binary tree
 * @return int整型二维数组
 */
function threeOrders( root ) {
    // write code here
    let res=[];
    let pre=[];
    let preOrder=((root)=>{
        if(root==null)
            return null;
        pre.push(root.val);
        preOrder(root.left);
        preOrder(root.right);
    })
    preOrder(root);
    res.push(pre);
    let In=[];
    let InOrder=((root)=>{
        if(root==null)
            return null;
        InOrder(root.left);
        In.push(root.val);
        InOrder(root.right);
    });
    InOrder(root);
    res.push(In);
    let post=[];
    let postOrder=((root)=>{
        if(root==null)
            return null;
       postOrder(root.left);
         postOrder(root.right);
        post.push(root.val);
    });
    res.push(post);
    postOrder(root)
    return res;
}
module.exports = {
    threeOrders : threeOrders
};

NC119 最小的K个数

描述

给定一个长度为 n 的可能有重复值的数组,找出其中不去重的最小的 k 个数。例如数组元素是4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4(任意顺序皆可)。

数据范围:0\le k,n \le 100000≤k,n≤10000,数组中每个数的大小0 \le val \le 10000≤val≤1000

要求:空间复杂度 O(n)O(n) ,时间复杂度 O(nlogn)O(nlogn)

示例1

输入:

[4,5,1,6,2,7,3,8],4 

返回值:

[1,2,3,4]

说明:

返回最小的4个数即可,返回[1,3,2,4]也可以        

示例2

输入:

[1],0

返回值:

[]

示例3

输入:

[0,1,2,1,2],3

返回值:

[0,1,1]

代码:

function GetLeastNumbers_Solution(input, k)
{
    // write code here
    input.sort(function(a,b){
        return a-b;
    });
    
    let arr=input.slice(0,k);
    return arr;
}
module.exports = {
    GetLeastNumbers_Solution : GetLeastNumbers_Solution
};

NC15 求二叉树的层序遍历

描述

给定一个二叉树,返回该二叉树层序遍历的结果,(从左到右,一层一层地遍历)
例如:
给定的二叉树是{3,9,20,#,#,15,7},
在这里插入图片描述

该二叉树层序遍历的结果是
[
[3],
[9,20],
[15,7]

]

数据范围:二叉树的节点数满足 1 \le n \le 10^5 \1≤n≤105

示例1

输入:

{1,2}

返回值:

[[1],[2]]

示例2

输入:

{1,2,3,4,#,#,5}

返回值:

[[1],[2,3],[4,5]]

代码:

/*
 * function TreeNode(x) {
 *   this.val = x;
 *   this.left = null;
 *   this.right = null;
 * }
 */

/**
  * 
  * @param root TreeNode类 
  * @return int整型二维数组
  */
function levelOrder( root ) {
//     最外层数组存储
   let res=[];
//     q存储层的节点
    let q=[];
//     将根节点存入q中
    q.push(root);
    
//         判断q当前的长度是否为0,如果为0则层序遍历结束
    while(q.length!=0){
//         存储当前q的长度
        let currentlength=q.length;
//         给存储数组推入一个空数组
        res.push([]);
//         循环遍历当前层的节点
        for(let i=0;i<currentlength;i++){
//             弹出q内的节点
            let node=q.shift();
//             将节点值存入res新加入的数组中
            res[res.length-1].push(node.val);
//             判断当前节点是否有左孩子
            if(node.left!=null)
//                 有则向q推入下层节点
                q.push(node.left);
//             同上
            if(node.right!=null)
                q.push(node.right);
        }
    }
    
    return res;
        
}
module.exports = {
    levelOrder : levelOrder
};

NC88 寻找第K大

描述

有一个整数数组,请你根据快速排序的思路,找出数组中第 k 大的数。

给定一个整数数组 a ,同时给定它的大小n和要找的 k ,请返回第 k 大的数(包括重复的元素,不用去重),保证答案存在。

要求:时间复杂度 O(nlogn)O(nlogn),空间复杂度 O(1)O(1)

数据范围:0\le n \le 10^50≤n≤105, 1 \le K \le n1≤Kn,数组中每个元素满足 0 \le val \le 10^90≤val≤109

示例1

输入:

[1,3,5,2,2],5,3

返回值:

2

示例2

输入:

[10,10,9,9,8,7,5,6,4,3,4,2],12,3

返回值:

9

说明:

去重后的第3大是8,但本题要求包含重复的元素,不用去重,所以输出9  

代码:

/**
 * 
 * @param a int整型一维数组 
 * @param n int整型 
 * @param K int整型 
 * @return int整型
 */
function findKth( a ,  n ,  K ) {
    // write code here
    a.sort(function(x,y){
        return y-x;
    })
    return a[K-1];
}
module.exports = {
    findKth : findKth
};

NC50 链表中的节点每k个一组翻转

描述

将给出的链表中的节点每 k 个一组翻转,返回翻转后的链表
如果链表中的节点数不是 k 的倍数,将最后剩下的节点保持原样
你不能更改节点中的值,只能更改节点本身。

数据范围: \ 0 \le n \le 2000 0≤n≤2000 , 1 \le k \le 20001≤k≤2000 ,链表中每个元素都满足 0 \le val \le 10000≤val≤1000
要求空间复杂度 O(1)O(1),时间复杂度 O(n)O(n)

例如:

给定的链表是 1\to2\to3\to4\to51→2→3→4→5

对于 k = 2k=2 , 你应该返回 2\to 1\to 4\to 3\to 52→1→4→3→5

对于 k = 3k=3 , 你应该返回 3\to2 \to1 \to 4\to 53→2→1→4→5

示例1

输入:

{1,2,3,4,5},2

返回值:

{2,1,4,3,5}

示例2

输入:

{},1

返回值:

{}

方法一(利用堆栈)

/*
 * function ListNode(x){
 *   this.val = x;
 *   this.next = null;
 * }
 */

/**
  * 
  * @param head ListNode类 
  * @param k int整型 
  * @return ListNode类
  */
function reverseKGroup( head ,  k ) {
    // write code here
//     方法一(堆栈)
//     arr存储节点
    let arr=[],p1=head,p2=null;
//    定义head1存储新链表
    let head1=new ListNode(null),count=0,p,sum=0;
//     令p指向head1
    p=head1;
    
//     计算链表长度
    while(p1){
        count++;
        p1=p1.next;
    }
//     当链表长度小于k时,直接返回链表
    if(count<k){
        return head;
    }
    let x=k;
//     遍历链表
    for(let i=0;i<count;i++){
//         重新给x赋值k个步长
        x=k;
//         遍历k个步长
        while(x){
//          将head.next暂存在p1中
            p1=head.next;
//          取出head的第一个节点
            head.next=null;
//           将第一个节点赋值给p2;
            p2=head;
//           将节点推入栈中
            arr.push(p2);
//          重新给head赋值回p1;
            head=p1;
//           步数减一
            x--;
//           总数加一
            sum++;
        }
//         重新给x赋值k个步长
        x=k;
        while(x){
//       使p节点的next指向arr弹出的节点,使head1.next指向arr弹出的节点    
            p.next=arr.pop();
//        使head1向后移动
            p=p.next;
            x--;
        }
//       链表长度减去总数小于k时直接将剩余的head赋值给head1,并退出循环
        if(count-sum<k){
            p.next=head;
            break;
        }
    }
    head1=head1.next;
    return head1;
    }

方法二(与方法一类似)

function reverseKGroup( head ,  k ) {
//     方法二(与堆栈类似)
    let p1=head,p2=null
    let head1=new ListNode(null),count=0,sum=0;
    let p=head1;
//    计算head长度
    while(p1){
        count++;
       p1=p1.next;
    }
    if(count<k){
        return head;
    }
    sum=count;
    let x=k;
    for(let i=0;i<count;i++){
        x=k;
        p2=null;
//      反转k个步长的链表,并存储在p2中
        while(x){
            p1=head.next;
            head.next=p2;
            p2=head;
            head=p1;
            x--;
        }
//    使节点p的next指向p2,head1中添加上p2   
       p.next=p2;
       x=k;
//     使p向后移动k个步长,至head1末尾    
       while(x){
           p=p.next;
           x--;
       }
//         总数减去k个步长
         sum=sum-k;
//         当总数小于k个步长时,直接将剩余的head接入head1中
        if(sum<k){
           p.next=head;
            break;
        } 
    }
    return head1.next;
  }  

方法三(大部分人的做法)

  function reverseKGroup( head ,  k ) {
   let pre = null
    let current = head
    let node = head
    for(let i = 0;i < k;i++) {
        if(node === null) {
            return head
        }
        node = node.next
    }
    for(let i = 0;i < k;i++) {
        let t= current.next
        current.next = pre
        pre = current
        current = t
    }
    head.next = reverseKGroup(current,k)
    return pre
    
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值