面试高频算法题


前言

恍恍惚惚的过了秋招,但是没有拿到理想的offer,这篇便是记边复习遍记录面试中比较高频的算法题,为接下来的春招做准备,冲鸭<( ̄︶ ̄)↗[GO!]


树的最基本遍历,用递归的方式是必须要掌握的,面试的时候基本是会让你用迭代的方式写出来,所以都得掌握

后序遍历

递归:

 class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        // 递归处理
        List<Integer> res=new ArrayList<>();
        postorderTraversalHelper(root,res); 
        return res;
       
    }
    public void postorderTraversalHelper(TreeNode node,List<Integer> res){
        if(node!=null){
            postorderTraversalHelper(node.left,res);
            postorderTraversalHelper(node.right,res);
            res.add(node.val);
        }
    }
}

迭代:

 class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        // 迭代处理
        // 方向来做
        // 后序遍历是左-》右-》中,那么反过来中-》右-》左,按照后面的顺序,把最后得到的结果反向过来就行
        List<Integer>res= new ArrayList<>();
        //  节点用栈来存储
        Stack<TreeNode> stack=new Stack<>();
        while(!stack.isEmpty() || root!=null){
            // 从中节点开始遍历完
            while(root!=null){
                res.add(root.val);
                stack.push(root);
                root=root.right;
            }
            root=stack.pop();
            root=root.left;
        }
        Collections.reverse(res);
        return res;
    }
}

前序遍历

递归:


 class Solution{
     List<Integer> res=new ArrayList<>();
     public List<Integer> preorderTraversal(TreeNode root){
        //  前序遍历是中-》左-》右
        // 递归的方式完成
        if(root!=null){
            res.add(root.val);
            preorderTraversal(root.left);
            preorderTraversal(root.right);
        }
        return res;
     }
 }

迭代:

class Solution{
    public List<Integer> preorderTraversal(TreeNode root){
        List<Integer> res=new ArrayList<>();
        // 用stack来保存结点
        Stack<TreeNode> stack=new Stack<>();
        while(!stack.isEmpty() || root!=null){
            while(root!=null){
                res.add(root.val);
                stack.push(root);
                root=root.left;
            }
            root=stack.pop();
            root=root.right;
        }
        return res;
    }
}

中序遍历

 class Solution{
     List<Integer> res=new ArrayList<>();
     public List<Integer> inorderTraversal(TreeNode root){
        //  递归就是左-》中-》右
        if(root!=null){
            inorderTraversal(root.left);
            res.add(root.val);
            inorderTraversal(root.right);
        }
        return res;
     }
 }

迭代:

class Solution{
    public List<Integer> inorderTraversal(TreeNode root){
        List<Integer> res=new ArrayList<>();
        Stack<TreeNode> stack=new Stack<>();
        while(!stack.isEmpty() || root!=null){
            while(root!=null){
                stack.push(root);
                root=root.left;
            }
            root=stack.pop();
            res.add(root.val);
            root=root.right;
        }
        return res;
    }
 }

二叉树的层次遍历

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res=new ArrayList<>();
        if(root == null){
            return res;
        }
        // 用两个队列分别记录不同层含有的结点,然后依次遍历
        Queue<TreeNode> A=new LinkedList<>();
        Queue<TreeNode> B= new LinkedList<>();
        A.offer(root);
        while(!A.isEmpty()){
            List<Integer> temp=new ArrayList<>();
            while(!A.isEmpty()){
                TreeNode node=A.poll();
                temp.add(node.val);
                if(node.left != null){
                    B.offer(node.left);
                }
                if(node.right !=null){
                    B.offer(node.right);
                }
            }
            res.add(temp);
            Queue<TreeNode> trans =A;
            A=B;
            B=trans;
        }
        return res;
    }
}

构建二叉树

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
   Map<Integer,Integer> map=new HashMap<>();
    int [] preorder;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        // 前序:中-》左-》右
        // 中序:左-》中-》右
        // 递归中,需要再每一层确定左右子树的范围
        // 查找的时候,用 map 会更快
        int length=inorder.length;
        this.preorder = preorder;
        for(int i=0;i<length;i++){
            map.put(inorder[i],i);// 记录在中序遍历中每个数字的位置,用 map 查找更快
        }
        return buildTreeHelper(0,0,length-1);

    }
    public TreeNode buildTreeHelper(int p_root,int i_left,int i_right){
        if(i_left>i_right){
            return null;
        }
        // 第一个便是根节点
        TreeNode root=new TreeNode(preorder[p_root]);
        // 找到左子树的范围
        // 定位根节点在中序遍历的位置
        int position=map.get(preorder[p_root]);
        root.left=buildTreeHelper(p_root+1,i_left,position-1);
        root.right=buildTreeHelper(position-i_left+p_root+1,position+1,i_right);
        return root;

    }
}

二叉搜索树中的插入操作

递归:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
 
 class Solution{
     public TreeNode insertIntoBST(TreeNode root,int val){
        //  使用递归
        // 为空比较特殊
        if(root==null){
            TreeNode node=new TreeNode(val);
            return node;
        }else if(root.val<val){
            root.right=insertIntoBST(root.right,val);
        }else {
            root.left=insertIntoBST(root.left,val);
        }
        return root;
     }
 }

迭代:

 
 class Solution{
     public TreeNode insertIntoBST(TreeNode root,int val){
        //  使用迭代
        // 为空比较特殊
        if(root ==null){
            return new TreeNode(val);
        }
        TreeNode temp=root;
        while(true){
            if(temp.val>val){
                if(temp.left==null){
                    temp.left=new TreeNode(val);
                    break;
                }
                temp=temp.left;
            }else{
                if(temp.right==null){
                    temp.right=new TreeNode(val);
                    break;
                }
                temp=temp.right;
            }
        }
        return root;
     }
 }

排序算法

1.冒泡排序

import java.util.*;

public class Main{
    public static void main(String [] args){
    //    冒泡排序
        int [] test =new int[]{3,5,6,23,67,1,35,67,90,5,6};
        int length=test.length;
        for(int i=0;i<length;++i){
            for(int j=0;j<length-i-1;j++){
                if(test[j]>test[j+1]){
                    int temp=test[j];
                    test[j]=test[j+1];
                    test[j+1]=temp;
                }
            }
        }
        System.out.println(Arrays.toString(test));
    }
}

2.快速排序


import java.util.Arrays;

public class Main{
    public static void main(String [] args){
    //    快速排序
        int [] test =new int[]{3,5,6,23,67,1,35,67,90,5,6};
        quicksort(test,0,test.length-1);
        System.out.println(Arrays.toString(test));

    }

    public static void quicksort(int [] num,int  left,int right){
        if(left<right){
            int temp= num[left];
            int l=left;
            int r=right;
            while(l<r){
                while(l<r && num[r]>temp){
                    r--;
                }
                if (l<r){
                    num[l]=num[r];
                    l++;
                }
                while(l<r && num[l]<temp){
                    l++;
                }
                if (l<r){
                    num[r]=num[l];
                    r--;
                }
            }
            num[l]=temp;
            quicksort(num,left,l-1);
            quicksort(num,l+1,right);
        }
    }
}

3.堆排序

import java.util.*;

public class Main{
    public static void main(String [] args){
    //    堆排序
        int [] test =new int[]{3,5,6,23,67,1,35,67,90,5,6};
        int length=test.length;
        for(int i=length/2-1;i>=0;--i){
            // 从最大的一个叶子节点的父节点开始
            heapsort(test,length,i);
        }
        for(int i=0;i<length;++i){
            int temp=test[0];
            test[0]=test[length-1-i];
            test[length-1-i]=temp;
            heapsort(test,length-1-i,0);
        }
        System.out.println(Arrays.toString(test));
    }
    public static void heapsort(int [] nums,int length,int position){
        // 先把要重新定位的数字保存起来
        int temp=nums[position];
        for(int k=2*position+1;k<length;k=2*k+1){
            if(k+1<length && nums[k+1]>nums[k]){
                k=k+1;
            }
            if(nums[k]>temp){
                nums[position]=nums[k];
                position=k;
            }else{
                break;
            }
        }
        nums[position]=temp;
    }
}

查找

二分查找(基本)


import java.util.*;

public class Main {
    public static void main(String [] args){
        int [] test=new int[] {2,3,4,5,6,7,9,10,15};
        // 二分查找
        System.out.print(search(test,11));


    }
    public static  boolean search(int [] nums ,int target){
        int length=nums.length;
        int left=0;
        int right=length-1;
        while(left<=right){
            int mid=left + (right-left)/2;
            if(nums[mid]== target){
                return true;
            }else if(nums[mid] >target){
                right=mid-1;
            }else{
                left=mid+1;
            }
        }
        return false;
    }

}

class Solution {
    public int searchInsert(int[] nums, int target) {
        int length;
        if(nums==null || (length=nums.length)==0){
            return 0;
        }
        if(nums[length-1]<target){
            return length;
        }
        int left=0;
        int right=length-1;
        while(left<right){
            int mid=left + (right-left)/2;
            if(nums[mid]<target){
                left=mid+1;
                
            }else{
                right=mid;
            }
        }
        return left;
    }
}

Java单例模式

public class Singleton {
    private volatile static Singleton singleton;
    private Singleton() {}

    public static Singleton getSingleton() {
        if(singleton == null){
            synchronized(Singleton.class){
                if (singleton ==null){
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

翻转链表

 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre =null; //前一个
        ListNode cur =head; //当前
        ListNode  next = null; //  指向下一个
        while (cur!=null) {
            next=cur.next;//保存下一个
            cur.next =pre; //翻转
            pre = cur;// 位置转移
            cur =next ;//位置转移
        }
        return pre;
    }
}

环形链表

/**
 * 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 || head.next==null){
            return false;
        }
        // 快慢指针来检测
        ListNode quick=head.next;
        ListNode slow =head;
        while(quick != null && quick.next !=null){
            if(quick ==slow ){
                return true;
            }
            quick =quick.next.next;
            slow= slow.next;
        }
        return false;
        
    }
}

环形链表 II

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode quick=head,slow=head;
        while(quick!=null && quick.next!=null){
            quick=quick.next.next;
            slow=slow.next;
            // 第一次相遇
            if(quick==slow){
                quick=head;
                // 第二次相遇
                while(quick !=slow){
                    slow=slow.next;
                    quick=quick.next;
                }
                return slow;
            }

        }
        return null;
    }
}

LRU缓存机制

class LRUCache {
    class Node{
        int key;
        int value;
        Node next;
        Node pre;
        public Node(int key,int value){
            this.value=value;
            this.key=key;
        }
    }
    int capacity;
    Map<Integer,Node> map=new HashMap<>();
    Node head,tail;
    public LRUCache(int capacity) {
        // 初始化
        this.capacity=capacity;
        head=new Node(-1,-1);
        tail=new Node(-1,-1);
        head.next=tail;
        tail.pre=head;
    }
    
    public int get(int key) {
        int res=-1;
        Node node;
        if(map.containsKey(key)){
            node =map.get(key);
            res=node.value;
        // 移动到队首
            deleteNode(node);
            putFirst(node);
        }
        return res;
    }
    
    public void put(int key, int value) {
          // 生成一个新的结点
            Node newNode=new Node(key,value);
        // 如果有相同的值,则覆盖
        if(map.containsKey(key)){
            Node node=deleteNode(map.get(key));
            map.remove(key);
        }else if(map.size()==capacity){
            // 删除链表中最后一个节点
            Node node=deleteNode(tail.pre);
            map.remove(node.key);      
        }
        map.put(key,newNode);
       // 放到队列头部
        putFirst(newNode);

    }
    public void putFirst(Node node){
        node.next=head.next;
        node.pre=head;
        head.next=node;
        node.next.pre=node;
    }
    public Node deleteNode(Node node){
        node.next.pre=node.pre;
        node.pre.next=node.next;
        return node;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值