牛客题霸-名企高频面试题

NC41 最长无重复子数组

滑动窗口+哈希表

import java.util.*;


public class Solution {
    /**
     * 
     * @param arr int整型一维数组 the array
     * @return int整型
     */
    public int maxLength (int[] arr) {
        // write code here
        int  l =0, r;
        int max = -1;
        HashMap<Integer,Integer> map = new HashMap<>();
        for( r = 0;r < arr.length;r++){
            //如果哈希表里有与最右边相同的数,把左边界依次右移,删除左边界的数,直到删除相同的数
            while(map.containsKey(arr[r])&l<=r){
                map.remove(arr[l]);
                l++;
            }
            //注意要先寻找哈希值,再加入哈希表
            map.put(arr[r],1);
            max = Math.max(max,r-l+1);
        }
        return max;
    }
}

NC68 跳台阶

经典斐波拉契数列


public class Solution {
    public int jumpFloor(int target) {
        //低一步,低两步
        int less1=2,less2=1,res=0;
        if(target==1||target==2)return target;
        for(int i = 3 ;i<=target;i++){
            res = less1 +less2;
            less2 = less1;
            less1 = res;
        }
        return res;
    }
}

一开始想用排列组合写的,但只能过一半的测试用例,大概是30左右就会溢出

public class Solution {
    public int jumpFloor(int target) {
        if(target == 0)return 0;
        //x两步,y一步
        int x,y;
        int sum = 0;
        for(x=0;x*2<=target;x++){
            y=target-x*2;
            //获取某种组合所有走法,C(y,x+y)
            sum += get(y,x+y);
        }
        return sum;
    }
    private int get(int a,int b){
        int res = 1;
        for(int i = 1 ;i<=a; i++,b--){
            res = res*b/i;
        }
        return res;
    }
}

NC93 设计LRU缓存结构

用双哈希表写了一个,测试用例过了7/17,有空再写链表

import java.util.*;


public class Solution {
    /**
     * lru design
     * @param operators int整型二维数组 the ops
     * @param k int整型 the k
     * @return int整型一维数组
     */
    public int[] LRU (int[][] arr, int k) {
        // write code here
        int len =(int) Arrays.stream(arr).filter(x->x[0] == 2).count();
        int[] a = new int[len];
        int j =0;
        //存放数值
        HashMap<Integer,Integer> mapx =new HashMap<>();
        //存放频繁度,1为最频繁
        HashMap<Integer,Integer> mapy =new HashMap<>();
        for(int i = 0;i<arr.length ;i++){
            if(arr[i][0]==1){
                mapx.put(arr[i][1],arr[i][2]);
                Set<Integer> keys = mapy.keySet();
                for(Integer key : keys){
                    if(mapy.get(key)==k){
                        mapx.remove(key);
//                         mapy.remove(key);
                    }
                    mapy.put(key,mapy.get(key)+1);
                    
                }
                mapy.put(arr[i][1],1);
            }else if((arr[i][0]==2)){
                int x=arr[i][1];
                if(mapx.containsKey(x)&&mapy.get(x)<=k){
                    int flag = mapy.get(x);
                    Set<Integer> keys = mapy.keySet();
                    for(Integer key : keys){
                            if(mapy.get(key)<flag){
                                mapy.put(key,mapy.get(key)+1);
                            }
                        }
                    mapy.put(x,1);
                    a[j++]=mapx.get(x);
                    }else{
                    a[j++]=-1;
                }
                }
            }
        return a;
        }
    }
import java.util.*;
 
public class Solution {
    /**
     * lru design
     * @param operators int整型二维数组 the ops
     * @param k int整型 the k
     * @return int整型一维数组
     */
    public int[] LRU (int[][] operators, int k) {
        // write code here
        Map<Integer, Integer> map = new LinkedHashMap<>();
        List<Integer> list = new LinkedList<>();
        for (int[] operator : operators) {
            int key = operator[1];
            switch(operator[0]) {
                case 1:
                    int value = operator[2];
                    if (map.size() < k) {
                        map.put(key, value);
                    } else {
                        Iterator it = map.keySet().iterator();
                        map.remove(it.next());
                        map.put(key, value);
                    }
                    break;
                case 2:
                    if (map.containsKey(key)) {
                        int val = map.get(key);
                        list.add(val);
                        map.remove(key);
                        map.put(key, val);
                    } else {
                        list.add(-1);
                    }
                    break;
                default:
            }
        }
        int[] res = new int[list.size()];
        int i = 0;
        for (int val : list) {
            res[i++] = val;
        }
        return res;
    }
}

NC76 用两个栈实现队列

import java.util.Stack;

public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    
    public void push(int node) {
       stack1.push(node);
    }
    
    public int pop() {
        //若stack2为空,吧stack1的元素全部入栈到stack2
        if(stack2.empty()){
            while(!stack1.empty()){
                stack2.push(stack1.pop());
            }
        }
        return stack2.pop();
    }
}

NC105 二分查找-II

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 如果目标值存在返回下标,否则返回 -1
     * @param nums int整型一维数组 
     * @param target int整型 
     * @return int整型
     */
    public int search (int[] nums, int target) {
        // write code here
        if (nums == null || nums.length == 0)return -1;
        int l = 0,r =nums.length-1;
        int res = search1(l,r,nums,target);
        //这里一定要先判断res>0,不然会出现越界
        while(res>0&&nums[res-1]==target)res--;
        return res;
    }
    
    private int search1(int l,int r,int[] nums,int tar){
        while(l<=r){
            int m =(l+r)/2;
            if(nums[m]==tar)return m;
            if(nums[m]>tar){
                r=m-1;
            }else{
                l=m+1;
            }
        }
        return -1;
     }
}

NC15 求二叉树的层序遍历

队列方法:

添加元素到队尾:add() 、offer();队列满时前者抛出一个 unchecked 异常,后者返回false

删除队首元素并返回:remove()、 poll();队列空时前者抛出异常,后者返回null

查询队首元素:element()、peek(); 队列空时前者抛出异常,后者返回null

Root = [1 , 2 , 3 , # , 4 , 5 , # , 6 ]

N = 1

Queue = [ 1 ] → [ 1 , 2 ] → [ 1 , 2 , 3 ] → [ 2 , 3 ]

Level = [ 1 ]

Res = [ 1 ]

N = 2

Queue = [ 2 , 3 ] → [ 2 , 3 ] → [ 2 , 3 , 4 ] → [ 3 , 4 ]

Level = [ 2 ]

Queue = [ 3 , 4 ] → [ 3 , 4 , 5 ] → [ 3 , 4 , 5 ] → [ 4 , 5 ]

Level = [ 2 , 3 ]

Res = [ [ 1 ] , [ 2 , 3 ] ]

N = 2

Queue = [ 4 , 5 ] → [ 4 , 5 , 6 ] → [ 4 , 5 , 6 ] → [ 5 , 6 ]

Level = [ 4 ]

Queue = [ 5 , 6 ] → [ 5 , 6 ] → [ 5 , 6 ] → [ 6 ]

Level = [ 4 , 5 ]

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

N = 1

Queue = [ 6 ] → [ 6 ] → [ 6 ] → [  ]

Level = [ 6 ]

Res = [ [ 1 ] , [ 2 , 3 ] , [ 4 , 5 ] , [ 6 ] ]

import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 * }
 */

public class Solution {
    /**
     * 
     * @param root TreeNode类 
     * @return int整型ArrayList<ArrayList<>>
     */
    public ArrayList<ArrayList<Integer>> levelOrder (TreeNode root) {
        // write code here
        ArrayList<ArrayList<Integer>> res = new  ArrayList<ArrayList<Integer>>();
        if(root == null)return res;
        Queue<TreeNode> queue =new LinkedList<TreeNode>();
        //根节点先进入队列
        queue.offer(root);
        while(!queue.isEmpty()){
            //level用于存储某层的所有结点
            ArrayList<Integer> level =new ArrayList<Integer>();
            //获取当前队列大小,即队列中的结点数量
            int n =queue.size();
            for(int i = 0;i<n;i++){
                //如果结点存在左右子节点,则进入队列,peek()返回队首元素,不删除
                if(queue.peek().left != null)queue.offer(queue.peek().left);
                if(queue.peek().right != null)queue.offer(queue.peek().right);
                //已经寻找子节点的节点(即队首)添加到level中,并出队
                level.add(queue.poll().val);
            }
            //将某层所有结点加入最终列表中
            res.add(level);
        }
        return res;
    }
}

NC4 判断链表中是否有环

快慢指针

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head == null)return false;
         ListNode fast=head,slow=head;
        while (null!=fast && null!=fast.next)
        {
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow)
                return true;
        }
        return false;
    }
}

NC102 在二叉树中找到两个节点的最近公共祖先

无脑遍历三次,第一次存父子映射,第二次找o1所有祖先,第三次从下往上找o2祖先,找到最近公共祖先

import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 * }
 */

public class Solution {
    /**
     * 
     * @param root TreeNode类 
     * @param o1 int整型 
     * @param o2 int整型 
     * @return int整型
     */
    public int lowestCommonAncestor (TreeNode root, int o1, int o2) {
        // write code here
        //结点,结点的父亲结点
        HashMap<Integer, Integer> map = new HashMap<Integer,Integer>();
        Queue<TreeNode> queue =new LinkedList<>();
        queue.offer(root);
        //val<=100,根节点的父亲结点设置为101即可
        map.put(root.val,101);
        //按层遍历,直到找到两个目标结点
        while(!map.containsKey(o1)||!map.containsKey(o2)){
            //查找队首结点的子节点
            TreeNode node =queue.poll();
            //有左结点则在哈希映射中加入该对父子结点,并把子节点入队
            if(node.left!=null){
                map.put(node.left.val,node.val);
                queue.offer(node.left);
            }
            if(node.right!=null){
                map.put(node.right.val,node.val);
                queue.offer(node.right);
            }
        }
        HashSet<Integer> father = new HashSet<>();
        //哈希映射里根节点的父亲结点是101
        //遍历所有O1的祖先加入到哈希表中
        while(o1!=101){
            father.add(o1);
            o1 = map.get(o1);
        }
        //从下往上找,第一个找到的共同祖先则是最近的公共祖先
        while(!father.contains(o2))o2=map.get(o2);
        return o2;
    }
}

NC19 连续子数组的最大和

[ 1 , 3 , -5 , 6 ]

a = 1 , sum = 1 , max = 1;

a = 3 , sum = 4 , max = 4;

a = -5 , sum = -1 , max = 4;

a = 6 , sum = 6 , max = 6;

当遍历到 -5 时,以-5结尾的子数组最大和为-1;

当遍历到 6 时,如果要加上前面的子数组,也就是加上 -5 的子数组最大和,即-1,则此时子数组最大和就是6本身,而不加上前面的子数组。

public class Solution {
    public int FindGreatestSumOfSubArray(int[] array) { 
        
        int max = Integer.MIN_VALUE;
        //sum表示以当前遍历的数的前一个数作为末尾,能获得的子数组的最大和
        int sum = 0;
        for(int a : array){
            //如果a的前一个数子数组最大和为负数,则将sum改为a,否则为sum+a
            sum = sum < 0 ? a : sum + a;
            //判断最大和 和 sum的大小
            max = Math.max(sum,max);
        }
        return max;
    }
}

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

本质都是递归入队,区别在于先序:根左右,中序:左根右,后续:左右根

import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 * }
 */

public class Solution {
    /**
     * 
     * @param root TreeNode类 the root of binary tree
     * @return int整型二维数组
     */
    public int[][] threeOrders (TreeNode root) {
        // write code here
        //三个列表存储前序、中序、后序遍历的结果
        List<Integer> listPre = new ArrayList<>();
        List<Integer> listIn = new ArrayList<>();
        List<Integer> listPost = new ArrayList<>();
 
        //调用函数计算遍历结果
        preOrder(root, listPre);
        inOrder(root, listIn);
        postOrder(root, listPost);
 
        //存放结果集
        int[][] res = new int[3][listPre.size()];
        for(int i = 0; i < listIn.size(); i++){
            res[0][i] = listPre.get(i);
            res[1][i] = listIn.get(i);
            res[2][i] = listPost.get(i);
 
        }
        return res;
    }
    // 先序遍历函数
    public void preOrder(TreeNode root, List<Integer> list){
      
        if(root == null)return;
        //根左右
        list.add(root.val);
        preOrder(root.left, list);
        preOrder(root.right, list);
    }
 
    // 中序遍历函数
    public void inOrder(TreeNode root, List<Integer> list){
        
        if(root == null)return;
       
       //左根右
        inOrder(root.left, list);
        list.add(root.val);
        inOrder(root.right, list);
    }
 
    // 后序遍历函数
    public void postOrder(TreeNode root, List<Integer> list){
        if(root == null)return;
        //左右根
        postOrder(root.left, list);
        postOrder(root.right, list);
        list.add(root.val);
    }
}

NC17 最长回文子串

import java.util.*;

public class Solution {
    public int getLongestPalindrome(String A, int n) {
        // write code here
        if(n==0)return 0;
        //回文串有可能为偶数长度也有可能为奇数长度
        //奇数情况下
        int max = 1;
        for(int i = 0;i<n;i++){
            int sum = 1;
            int left = i ,right = i;
            while(left-1>=0&&right+1<n){
                left--;
                right++;
                if(A.charAt(left)==A.charAt(right)){
                    sum += 2;
                    max=Math.max(sum,max);
                }else{
                    left = -1;
                }
            }
        }
        //偶数情况下,找到相邻两个相同的字符
        for(int i =0;i+1<n;i++){
            if(A.charAt(i)==A.charAt(i+1)){
                int sum = 2 ;
                //极端情况,"aa"
                max=Math.max(sum,max);
                int left = i,right = i +1;
                while(left-1>=0&&right+1<n){
                    left--;
                    right++;
                    if(A.charAt(left)==A.charAt(right)){
                        sum+=2;
                        max=Math.max(sum,max);
                    }else{
                        left = -1;
                    }
                }
            }
        }
        return max;
    }
}

NC14 按之字形顺序打印二叉树


import java.util.*;
/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public ArrayList<ArrayList<Integer> > Print(TreeNode root) {
        ArrayList<ArrayList<Integer>> res = new  ArrayList<ArrayList<Integer>>();
        if(root == null)return res;
        Queue<TreeNode> queue =new LinkedList<TreeNode>();
        //根节点先进入队列
        queue.offer(root);
        int flag = 1;
        while(!queue.isEmpty()){
            //level用于存储某层的所有结点
            ArrayList<Integer> level =new ArrayList<Integer>();
            //获取当前队列大小,即队列中的结点数量
            int n =queue.size();
            for(int i = 0;i<n;i++){
                //如果结点存在左右子节点,则进入队列,peek()返回队首元素,不删除
                if(queue.peek().left != null)queue.offer(queue.peek().left);
                if(queue.peek().right != null)queue.offer(queue.peek().right);
                //已经寻找子节点的节点(即队首)添加到level中,并出队
                level.add(queue.poll().val);
            }
            //将某层所有结点加入最终列表中
            if(flag==-1){
                Collections.reverse(level);
            }
            res.add(level);
            flag*=-1;
        }
        return res;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值