算法笔试面试2

用两个栈来模拟实现队列

public class MyQueue {

    private static Stack<Integer> inStack;
    private static Stack<Integer> outStack;

    public MyQueue(){
        inStack = new Stack<>();
        outStack = new Stack<>();
    }

    // 像队列中push元素
    public void push(int x){
        inStack.push(x);
    }

    // 从队列中弹出元素
    public int pop(){
        if (outStack.isEmpty()){
            in2out();
        }
        return outStack.pop();
    }

    // 查看队首元素,但是不取出
    public int peek(){
        if(outStack.isEmpty()){
            in2out();
        }
        return outStack.peek();
    }

    public boolean isEmpty(){
        return inStack.isEmpty() && outStack.isEmpty();
    }

    public void in2out(){
        while (!inStack.isEmpty()){
            outStack.push(inStack.pop());
        }
    }

}

字符串解码

// TODO 待理解

public class Solution {

    int ptr;

    public String decodeString(String s) {

        LinkedList<String> stk = new LinkedList<>();
        ptr = 0;

        while (ptr < s.length()) {
            // 获取当前位置的字符
            char cur = s.charAt(ptr);
            // 判断当前字符是否是数字
            if (Character.isDigit(cur)) {
                // 处理数字,使数字完整
                String digits = getDigits(s);
                // 压入栈中
                stk.addLast(digits);
            } else if (Character.isLetter(cur) || cur == '[') {
                // 处理普通字符和[
                stk.addLast(String.valueOf(s.charAt(ptr++)));
            } else {
                // 遇见了] ,处理相匹配的[之间的字符
                ++ptr;
                // 使用领一个list,将字符串进行组合
                LinkedList<String> sub = new LinkedList<>();
                // 如果不是[,就一直出栈,将出栈的元素放入到新建的sub栈中
                while (!"[".equals(stk.peekLast())) {
                    sub.addLast(stk.removeLast());
                }
                // 因为栈的特点,导致组合的字符串和原本的字符串相比是倒序的,需要翻转一次
                Collections.reverse(sub);
                // 左括号[出栈
                stk.removeLast();
                // 此时栈顶为当前sub对应的字符串应该出现的次数
                int repTime = Integer.parseInt(stk.removeLast());
                StringBuffer t = new StringBuffer();
                String o = getString(sub);
                // 构造字符串
                while (repTime-- > 0) {
                    t.append(o);
                }
                // 构造字符串
                while (repTime-- > 0) {
                    t.append(o);
                }
                // 构造好的字符串入栈
                stk.addLast(t.toString());

            }

        }
        return getString(stk);


    }

    public String getDigits(String s) {
        StringBuffer ret = new StringBuffer();
        while (Character.isDigit(s.charAt(ptr))) {
            ret.append(s.charAt(ptr++));
        }
        return ret.toString();
    }

    public String getString(LinkedList<String> v) {
        StringBuffer ret = new StringBuffer();
        for (String s : v) {
            ret.append(s);
        }
        return ret.toString();
    }

    public static void main(String[] args) {
        String s = "3[a]2[bc]";
        Solution solution = new Solution();
        String ret = solution.decodeString(s);
        System.out.println(ret);
    }

}

二叉树的中序遍历

方式一:采用递归的的方式

public class Solution {

    public static 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;
        }
    }

    public List<Integer> inorderTraversal(TreeNode root) {

        List<Integer> res = new ArrayList<>();
        accessTree(root, res);

        return res;
    }

    private void accessTree(TreeNode root, List<Integer> res) {
        if (null == root) {
            return;
        }
        // 说白了就是使用递归的方式进行遍历
        accessTree(root.left, res);
        res.add(root.val);
        accessTree(root.right, res);
    }

    public static void main(String[] args) {
        TreeNode left = new TreeNode(2,null,null);
        TreeNode right = new TreeNode(3,null,null);
        TreeNode root = new TreeNode(1,left,right);

        Solution solution = new Solution();
        List<Integer> treeList = solution.inorderTraversal(root);
        System.out.println(treeList);

    }

}

方式二:采用循环爹迭代的方式(借助栈)

    public List<Integer> inorderTraversal(TreeNode root) {

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

二叉树的前序遍历

public class Solution {

    public static 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;
        }
    }


    public List<Integer> inorderTraversal(TreeNode root) {

        List<Integer> res = new ArrayList<>();
        accessTree(root, res);

        return res;
    }

    private void accessTree(TreeNode root, List<Integer> res) {
        if (null == root) {
            return;
        }
        // 说白了就是使用递归的方式进行遍历
        res.add(root.val);
        accessTree(root.left, res);
        accessTree(root.right, res);
    }

    public static void main(String[] args) {
        TreeNode left = new TreeNode(2,null,null);
        TreeNode right = new TreeNode(3,null,null);
        TreeNode root = new TreeNode(1,left,right);

        Solution solution = new Solution();
        List<Integer> treeList = solution.inorderTraversal(root);
        System.out.println(treeList);

    }

}

二叉树的后续遍历

public class Solution {

    public static 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;
        }
    }


    public List<Integer> inorderTraversal(TreeNode root) {

        List<Integer> res = new ArrayList<>();
        accessTree(root, res);

        return res;
    }

    private void accessTree(TreeNode root, List<Integer> res) {
        if (null == root) {
            return;
        }
        // 说白了就是使用递归的方式进行遍历
        accessTree(root.left, res);
        accessTree(root.right, res);
        res.add(root.val);
    }

    public static void main(String[] args) {
        TreeNode left = new TreeNode(2,null,null);
        TreeNode right = new TreeNode(3,null,null);
        TreeNode root = new TreeNode(1,left,right);

        Solution solution = new Solution();
        List<Integer> treeList = solution.inorderTraversal(root);
        System.out.println(treeList);

    }

}

对称二叉树

public class Solution {

    public static 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;
        }
    }


    public boolean isSymmetric(TreeNode root) {
        if(root == null){
            return true;
        }

        // 调用递归函数,比较左节点、右节点
        return deepCheck(root.left,root.right);
    }

    private boolean deepCheck(TreeNode left, TreeNode right) {
        // 递归的终止条件是两个节点都为空
        // 或者两个节点中有一个为空
        // 或者两个节点的值不相等
        if(left == null && right == null){
            return true;
        }
        if(left == null || right == null){
            return false;
        }
        if (left.val != right.val){
            return false;
        }

        // 再递归的比较 左节点的左孩子 和 右节点的右孩子
        // 以及比较 左节点的右孩子 和右节点的左孩子
        return deepCheck(left.left,right.right) && deepCheck(left.right,right.left);
    }



    public static void main(String[] args) {
        TreeNode left = new TreeNode(2,null,null);
        TreeNode right = new TreeNode(2,null,null);
        TreeNode root = new TreeNode(1,left,right);

        Solution solution = new Solution();
        boolean flag= solution.isSymmetric(root);
        System.out.println(flag);

    }

}

二叉树的深度

public class Solution {

    public static 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;
        }
    }


    public int maxDepth(TreeNode root) {
        if(root == null){
            return 0;
        }

        return Math.max(maxDepth(root.left),maxDepth(root.right))+1;
    }


    public static void main(String[] args) {
        TreeNode left = new TreeNode(2,null,null);
        TreeNode right = new TreeNode(2,null,null);
        TreeNode root = new TreeNode(1,left,right);

        Solution solution = new Solution();
        int depth = solution.maxDepth(root);
        System.out.println(depth);

    }

}

平衡二叉树

public class Solution {

    public static 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;
        }
    }


    public boolean isBalanced(TreeNode root) {
        if(root == null){
            return true;
        }

        return helper(root) != -1;
    }

    private int helper(TreeNode root) {
        if(root == null){
            return 0;
        }
        // 进行递归调用
        int left = helper(root.left);
        int right = helper(root.right);
        if(left == -1 || right == -1 || Math.abs(left-right)>1){
            return -1;
        }

        return Math.max(left,right)+1;
    }


    public static void main(String[] args) {
        // 平衡二叉树
//        TreeNode left = new TreeNode(2,null,null);
//        TreeNode right = new TreeNode(2,null,null);
//        TreeNode root = new TreeNode(1,left,right);

        // 非平衡二叉树
        TreeNode child01left = new TreeNode(2,null,null);
        TreeNode child02left = new TreeNode(2,null,null);
        TreeNode left = new TreeNode(2,child01left,null);
        child01left.left = child02left;
        TreeNode right = new TreeNode(2,null,null);
        TreeNode root = new TreeNode(1,left,right);

        Solution solution = new Solution();
        boolean flag = solution.isBalanced(root);
        System.out.println(flag);

    }

}

翻转二叉树

public class Solution {

    public static 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;
        }
    }


    public TreeNode invertTree(TreeNode root) {
        if(root == null){
            return null;
        }
        invertTree(root.left);
        invertTree(root.right);
        TreeNode temp = root.left;
        root.left = root.right;
        root.right = temp;

        return root;
    }


    // 二叉树的前序中序遍历
    public List<Integer> inorderTraversal(TreeNode root) {

        List<Integer> res = new ArrayList<>();
        accessTree(root, res);

        return res;
    }

    private void accessTree(TreeNode root, List<Integer> res) {
        if (null == root) {
            return;
        }
        // 说白了就是使用递归的方式进行遍历
        accessTree(root.left, res);
        res.add(root.val);
        accessTree(root.right, res);

    }



    public static void main(String[] args) {


        // 非平衡二叉树
        TreeNode child01left = new TreeNode(1,null,null);
        TreeNode child01right = new TreeNode(3,null,null);
        TreeNode left = new TreeNode(2,child01left,child01right);

        TreeNode child02left = new TreeNode(5,null,null);
        TreeNode child02right = new TreeNode(7,null,null);
        TreeNode right = new TreeNode(6,child02left,child02right);

        TreeNode root = new TreeNode(4,left,right);

        Solution solution = new Solution();
        TreeNode node = solution.invertTree(root);
        List<Integer> nodelist = solution.inorderTraversal(node);
        System.out.println(nodelist);

    }

}

LRU算法

定义:最近最少使用

底层基于 哈希表 + 双向链表 的数据结构来实现。

方式一:使用linkedhashmap来实现

public class LRUCacheByLinkedHashMap {

    LinkedHashMap<Integer, Integer> map = null;
    int capacity;

    public LRUCacheByLinkedHashMap(int capacity){
        map = new LinkedHashMap<>(capacity + 1, 0.75f,true);
        this.capacity = capacity;
    }

    public int get(int key){
        if (!map.containsKey(key)){
            return -1;
        }

        return map.get(key);
    }

    public void put(int key,int value){
        map.put(key,value);
        if (map.size() > capacity){
            Iterator<Integer> iterator = map.keySet().iterator();
            map.remove(iterator.next());
        }
    }
}

方式二:使用HashMap实现

public class LRUCacheByHashMap {

    class Node {
        Node next;
        Node pre;
        int key;
        int value;

        Node(int k, int v) {
            next = this;
            pre = this;
            key = k;
            value = v;
        }
    }

    HashMap<Integer,Node> map= new HashMap<>();
    int capacity;
    Node head;

    public LRUCacheByHashMap(int capacity){
        this.capacity= capacity;
        head = new Node(-1,-1);
    }

    public int get(int key){
        if(!map.containsKey(key)){
            return -1;
        }
        Node node = map.get(key);
        refresh(node); // 将取出来的这个节点刷新到头部
        return node.value;
    }

    public void put(int key,int value){
        if(map.containsKey(key)){
            Node node = map.get(key);
            node.value = value;
            refresh(node);
        }else {
            Node node = new Node(key,value);
            map.put(key,node);
            refresh(node);
            if(map.size() > capacity){
                del();
            }
        }
    }

    private void refresh(Node node){
        // 将这个node节点摘除
        node.next.pre = node.pre;
        node.pre.next = node.next;

        node.next = head.next;
        head.next.pre = node;
        head.next = node;
        node.pre = head;
    }

    // 删除队尾
    private void del(){
        Node node = head.pre;
        node.next.pre = node.pre;
        node.pre.next = node.next;
        map.remove(node.key);
    }


}

限制短信发送速率

// 假设我们有一个包含所有需要发送短信的电话号码的列表
List<String> phoneNumbers = Arrays.asList("1234567890", "0987654321", ...);
 
// 设置限速参数
int maxSmsPerSecond = 10;  // 每秒最多发送的短信数量
int intervalBetweenSms = 1000 / maxSmsPerSecond;  // 每条短信之间的间隔时间(毫秒)
 
// 记录上一次发送短信的时间
long lastSendTime = System.currentTimeMillis();
 
// 遍历电话号码列表,逐个发送短信
for (String phoneNumber : phoneNumbers) {
    // 检查是否需要等待以满足限速要求
    long currentTime = System.currentTimeMillis();
    if (currentTime - lastSendTime < intervalBetweenSms) {
        // 计算需要等待的时间
        long waitTime = intervalBetweenSms - (currentTime - lastSendTime);
        Thread.sleep(waitTime);
    }
 
    // 发送短信
    sendSms("Your message here", phoneNumber);
 
    // 更新上一次发送短信的时间
    lastSendTime = System.currentTimeMillis();
}

输入一个字符串,统计字符串中每个字符出现的次数;输出字符及其对应的次数,按字符升序排列。

/**
 * 编写一个 Java 程序,实现以下功能:
 * 输入一个字符串,统计字符串中每个字符出现的次数;输出字符及其对应的次数,按字符升序排列。
 * 示例输入:aaabbc
 * 示例输出:a:3, b:2, c:1
 */
public class Solution {


    public String countOfPerCharacter(String content) {

        if (null == content || 0 == content.length()) {
            return "字符串为空";
        }

        String[] arr = content.split("");
        Map<String, Integer> map = new TreeMap<>();

        for (int i = 0; i < arr.length; i++) {
            if (map.containsKey(arr[i])) {
                map.put(arr[i], map.get(arr[i]) + 1);
            }else{
                map.put(arr[i], 1);
            }

        }

        // 使用TreeMap对字符串进行升序排序存储
        StringBuilder result = new StringBuilder();

        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            result.append(entry.getKey() + ":" + entry.getValue());
        }

        return result.toString();
    }

    public static void main(String[] args) {
        String input = "aaabbc";
        Solution solution = new Solution();
        System.out.println(solution.countOfPerCharacter(input));

    }
}

posted on 2024-11-23 17:45  ~码铃薯~  阅读(3)  评论(0编辑  收藏  举报

导航