当前位置: 首页 > news >正文

面试常考简单操作

参考文章

面试常考简单操作

    • 快速排序
    • 归并排序
    • Dijkstra
    • 自定义排序
    • 交替打印奇偶数
    • 冒泡排序
    • 插入排序
    • 堆排序
    • 欧几里得算法求最大公约数
    • 单例模式的双重校验
    • LRU

快速排序

public class Solution {

    private static int partition(int[] arr, int left, int right) {
        int temp = arr[left];	// 1
        while(left < right) {
            while(left < right && temp <= arr[right]) right--;
            arr[left] = arr[right];	// 2
            while(left < right && temp >= arr[left]) left++;
            arr[right] = arr[left];	// 3
        }
        arr[left] = temp;	// 4
        return left;
    }

    private static void quicSort(int[] arr, int left, int right) {
        if(left<right) {
            int mid = partition(arr, left, right);
            quicSort(arr,left, mid-1);
            quicSort(arr,mid+1, right);
        }
    }

    public static void main(String[] args) {
        int[] arr = {3,5,1,32,8,5,3,0};
        quicSort(arr, 0, arr.length-1);
        Arrays.stream(arr).forEach((n)->{
            System.out.print(n + " ");
        });
    }
}
  • 时间复杂度O( n l o g n nlogn nlogn):快排使用的是递归,需要做logn次分割,而每次划分需要找对应的基准元素,需要O(n)时间。
  • 空间复杂度O( l o g n logn logn):平均情况下,递归树的高度为logn。

归并排序

public class Solution {

	// 主要是这里,对于两个有序数组合并,是挺简单的。
	// 如何把它拆分出来是一个问题。
    private static int[] mergeSort(int[] arr, int left, int right) {
        if(left == right) { //长度为1,直接放回
            return new int[]{arr[left]};
        }
        int mid = ((right - left) >> 1 ) + left;
        int[] l = mergeSort(arr, left, mid);
        int[] r = mergeSort(arr, mid+1, right);
        return mergeTwoArray(l,r);
    }

	// 归并思想挺简单的,如下
    private static int[] mergeTwoArray(int[] l, int[] r) {
        int[] res = new int[l.length+r.length];
        int left = 0, right = 0, index = 0;
        while(left < l.length && right < r.length) {
            if(l[left] < r[right]) {
                res[index++] = l[left++];
            }else {
                res[index++] = r[right++];
            }
        }
        while(left < l.length) {
            res[index++] = l[left++];
        }
        while(right < r.length) {
            res[index++] = r[right++];
        }
        return res;
    }



    public static void main(String[] args) {
        int[] arr = {3,5,1,32,8,5,3,0};
        int[] res = mergeSort(arr, 0, arr.length-1);    // 注意这里不是原地排序的,是新开辟一个空间
        Arrays.stream(res).forEach((n)->{
            System.out.print(n + " ");
        });
    }
}
  • 时间复杂度O( n l o g n nlogn nlogn):无论原始数组的顺序如何,归并排序都需要将数组不断地分成两半,然后再合并,总共需要进行logn
    层的划分和合并操作,每层操作都需要遍历 O(n)个元素。

  • 空间复杂度O( n n n):需要额外的辅助数组。

Dijkstra

package com.zy;

import java.util.Arrays;

public class Solution {

    private static final int INF = Integer.MAX_VALUE;

    public static int[] dijkstra(int[][] graph, int src) {
        int n = graph.length;
        int[] dist = new int[n];
        boolean[] sptSet = new boolean[n];

        //初始化距离数组和最短路径集合
        Arrays.fill(dist, INF);
        dist[src] = 0;

        // 每次循环找到距离src最近的一个节点,总共循环n-1次
        for (int count = 0; count < n - 1; count++) {
            //找到最近节点u
            int u = minDistance(dist, sptSet);
            sptSet[u] = true;

            // 加入u后,各个节点的变化
            for (int v = 0; v < n; v++) {
                // 要是还没处理,且u和v是可达的,且刚刚更新的最近节点u不是不可达的,且更新后的距离更短
                if (!sptSet[v] && graph[u][v] != 0 && dist[u] != INF && dist[u] + graph[u][v] < dist[v]) {
                    dist[v] = dist[u] + graph[u][v];
                }
            }
        }

        return dist;
    }

    private static int minDistance(int[] dist, boolean[] sptSet) {
        int min = INF, minIndex = -1;
        for (int v = 0; v < dist.length; v++) {
            if (!sptSet[v] && dist[v] <= min) {
                min = dist[v];
                minIndex = v;
            }
        }
        return minIndex;
    }


    public static void main(String[] args) {
        int[][] graph = {
                {0, 4, 0, 0, 0, 0, 0, 8, 0},
                {4, 0, 8, 0, 0, 0, 0, 11, 0},
                {0, 8, 0, 7, 0, 4, 0, 0, 2},
                {0, 0, 7, 0, 9, 14, 0, 0, 0},
                {0, 0, 0, 9, 0, 10, 0, 0, 0},
                {0, 0, 4, 14, 10, 0, 2, 0, 0},
                {0, 0, 0, 0, 0, 2, 0, 1, 6},
                {8, 11, 0, 0, 0, 0, 1, 0, 7},
                {0, 0, 2, 0, 0, 0, 6, 7, 0}
        };
        int src = 0;
        int[] dist = dijkstra(graph, src);
        System.out.println("从顶点 " + src + " 到各顶点的最短距离为:");
        for (int i = 0; i < dist.length; i++) {
            System.out.println("到顶点 " + i + " 的最短距离是:" + dist[i]);
        }
    }
}
  • 时间复杂度O( n 2 n^2 n2):由于使用了邻接矩阵存储图,每次查找距离源点最近的顶点需要遍历所有顶点,更新距离也需要遍历所有顶点。
  • 空间复杂度O( n n n):主要使用了 dist 数组和 sptSet 数组来存储距离和标记顶点是否已处理

自定义排序

思考Comparator和Comparable的区别
在这里插入图片描述

实现Comparator接口实现。

package com.zy;

import java.util.Arrays;
import java.util.Comparator;

class Student implements Comparable<Student>{
    int age;
    int score;

    public Student(int age, int score) {
        this.age = age;
        this.score = score;
    }


    @Override
    public int compareTo(Student o) {
        if(this.age != o.age) {
            return this.age - o.age;
        }
        return o.score - this.score;
    }
}

public class Solution {
    public static void main(String[] args) {
        Student[] stu = new Student[3];
        stu[0] = new Student(10,13);
        stu[1] = new Student(5, 4);
        stu[2] = new Student(5,33);

        // 法1
        Arrays.sort(stu, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                if(o1.age != o2.age) {
                    return o1.age - o2.age;
                }
                return o2.score - o1.score;
            }
        });


        // 法2
        Arrays.sort(stu, (o1,o2)-> {
            if(o1.age != o2.age) {
                return o1.age - o2.age;
            }
            return o2.score - o1.score;
        });

        // 法3(用Comparable实现默认排序)
        Arrays.sort(stu);

        Arrays.stream(stu).forEach(student -> {
            System.out.println(student.age + " " + student.score);
        });


    }
}

交替打印奇偶数

package com.zy;

class AlterPrint {

    private static final Object lock = new Object();
    private static final int MAX = 200;
    private static int count = 0;

    // 打印,唤醒,看有没有终止,有就结束,没有就等待
    void printNumber() {
        synchronized (lock) {
            while(true) {
                System.out.println(Thread.currentThread().getName() + "打印" + count++);
                lock.notify();
                if(count>=MAX) {
                	lock.notifyAll(); //在彻底退出之前,最好都唤醒,不然某些线程会一直等待。
                    break;
                }
                try {
                    lock.wait();
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

public class Solution {

    public static void main(String[] args) {
        // 实现两个线程交替打印奇偶
        AlterPrint alterPrint = new AlterPrint();
        Thread thread0 = new Thread(alterPrint::printNumber, "线程1");
        Thread thread1 = new Thread(alterPrint::printNumber, "线程2");

        thread0.start();
        thread1.start();
    }

}

冒泡排序

public class Solution {

    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    private static void bubbleSort(int[] arr) {
        for(int i=0;i<arr.length;i++) {
            boolean flag = true;
            for(int j=arr.length-1;j>i;j--) {
                if(arr[j-1] > arr[j]) {
                    swap(arr, j-1, j);
                    flag = false;
                }
            }
            if(flag) break;
        }
    }

    public static void main(String[] args) {
        int[] arr = {3,4,6,8,3,1,0,22,10};
        bubbleSort(arr);
        for(int i : arr) {
            System.out.println(i);
        }
    }

}

插入排序

public class Solution {
    private static void InsertSort(int[] arr) {
        for(int i=1;i<arr.length;i++) {
            int key = arr[i];   // 要排序的数字
            int j = i-1;    // 从有序数组的尾部开始比较
            while(j >= 0 && arr[j] > key) {
                arr[j + 1] = arr[j];
                j = j - 1;
            }
            arr[j + 1] = key;
        }
    }

    public static void main(String[] args) {
        int[] arr = {3,4,6,8,3,1,0,22,10};
        InsertSort(arr);
        for(int i : arr) {
            System.out.println(i);
        }
    }
}

堆排序

package com.zy;


import java.util.Scanner;

public class Main {

    // 调整有效大小为n的堆中的i节点
    private static void adjust(int[] nums, int n, int i) {
        int largest = i;
        int left = 2 * i + 1;
        int right = 2 * i + 2;
        // 找左右节点跟节点i中最大的节点索引 : largest
        if(left < n && nums[left] > nums[largest]) {
            largest = left;
        }
        if(right < n && nums[right] > nums[largest]) {
            largest = right;
        }

        if(largest != i) {  // 如果节点i需要往下调整
                            // 跟最大的节点替换后
            int tmp = nums[i];
            nums[i] = nums[largest];
            nums[largest] = tmp;
                            // 接着继续向下调整
            adjust(nums,n,largest);
        }
    }

    private static void heapSort(int[] arr) {
        int n = arr.length;

        // 调整数组,使得父节点>子节点,从最后一个非叶子节点开始
        for(int i=n/2-1;i>=0;i--) {     // 自己小推一下就知道了
            adjust(arr, n, i);
        }
        // i*2-1

        for(int i=n-1;i>0;i--) {
            // 当前父节点移动到末尾(这里他就是排到正确位置了)
            int temp = arr[0];
            arr[0] = arr[i];
            arr[i] = temp;
            // 剩下部分继续调整
            adjust(arr, i, 0);
        }
    }

    public static void main(String[] args) {
        int[] arr = {3,1,2,5,7,4};
        heapSort(arr);
        for(int num : arr) {
            System.out.print(num + " ");
        }
    }
}

欧几里得算法求最大公约数

static int gcb(int a, int b) {
    if(b==0) return a;
    return gcb(b, a%b);
}

单例模式的双重校验

package com.zy;

public class Singleton {
    private volatile static Singleton singletonInstance;

    private Singleton(){}

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

LRU


http://www.dtcms.com/a/107841.html

相关文章:

  • ADS7822中文技术手册
  • Burp靶场 - HTTP走私请求【Part2】
  • Elasticsearch collapse 的使用场景及作用机制
  • Linux驱动开发实战(十一):GPIO子系统深度解析与RGB LED驱动实践
  • es 集群存储字典 json字段----python实现
  • Conda安装ffmpeg
  • idea查看class字节码
  • Java高频面试题1:Java SE
  • SpaceX星舰商业载人首绕月球:私人太空旅行时代正式开启
  • mycat --分片规则--
  • [Android] 共生地球 v1.1.19 国产卫星地图
  • 详细介绍一下C++中的extern关键字
  • 搭建qemu环境
  • 【pcdet3D检测】——OPenpcdet如何进行测试文件配置?能否自定义测试数据?一文看懂pointpillar(pcdet)中的test.py
  • redis7.0搭建redis-cluster集群部署实战
  • AquaMoon and Chess_CodeForces - 1545B
  • AI前沿:资本狂潮下的技术暗战:巨头博弈、开源革命与生态重构
  • Java项目之基于ssm的简易版营业厅宽带系统(源码+文档)
  • Ubuntu 使用apt安装MySQL后的升级方法
  • Share02-小小脚本大大能量
  • 【面试篇】多线程
  • RTX5080 安装torch,torchvision ,torchaudio 指南
  • 全功能在线WEB工具箱PHP源码
  • 3. 线程间共享数据
  • 跨网文件安全交换系统|国产信创认证+安全高效传输
  • 2025-4-2 蓝桥杯刷题情况(分布式队列)
  • 智能觉醒:四大AI Agent框架重构未来生产力
  • 简单描述一下Unity物理系统的主要性能消耗点
  • 【高项】信息系统项目管理师(十五)高级项目管理【4分】
  • RocketMq 5.0之后延时消息底层是怎么实现的?