算法面试题

内容分类详情
Java高频面试题汇总入口
JVMJVM面试题
并发并发面试题
SpringSpring面试题
分布式分布式面试题
SpringBootSpringBoot面试题
SpringCloudSpringCloud面试题
DubboDubbo面试题
MySQLMySQL面试题
MybatisMybatis面试题
RedisRedis面试题
RocketMQRocketMQ面试题
算法算法面试题
遇到的问题遇到的问题
面试官的其他问题面试官的其他问题
GitGit面试题

雪花算法

四个组成部分

不使用 :1bit,最高位是符号位,0 表示正,1 表示负,固定为 0

时间戳 :41bit,毫秒级的时间戳(41 位的长度可以使用 69 年)

标识位 :5bit 数据中心 ID,5bit 工作机器 ID,两个标识位组合起来最多可以支持部署 1024 个节点

序列号 :12bit 递增序列号,表示节点毫秒内生成重复,通过序列号表示唯一,12bit 每毫秒可产生 4096 个 ID

优点:
高性能高可用:生成时不依赖于数据库,完全在内存中生成

高吞吐:每秒钟能生成数百万的自增 ID

ID 自增:存入数据库中,索引效率高

排序算法

冒泡排序

  1. 外层循环控制几轮对比
  2. 内层控制每轮对比次数
  3. 内层相邻两个元素比较,并交换
for (int i = 0; i < list.size() - 1; i++) {
    for (int j = 0; j < list.size() - i - 1; j++) {
        int max = list.get(j);
        if (list.get(j) > list.get(j + 1)) {
            list.set(j, list.get(j + 1));
            list.set(j + 1, max);
        }
    }
}

选择排序

在这里插入图片描述

每轮循环和剩下的元素对比找到最小值,并替换。

for (int i = 0; i < list.size(); i++) {
    for (int j = i + 1; j < list.size(); j++) {
        int temp = list.get(i);
        if (list.get(i) > list.get(j)) {
            list.set(i, list.get(j));
            list.set(j, temp);
        }
    }
}

插入排序

在这里插入图片描述

/**
    * 升序
    * 待比较数据:7, 6, 9, 8, 5,1
    *   第一轮:指针指向第二个元素6,假设6左面的元素为有序的,将6抽离出来,形成7,_,9,8,5,1,从7开始,6和7比较,发现7>6。将7右移,形成_,7,9,8,5,1,6插入到7前面的空位,结果:6,7,9,8,5,1
    *   第二轮:指针指向第三个元素9,此时其左面的元素6,7为有序的,将9抽离出来,形成6,7,_,8,5,1,从7开始,依次与9比较,发现9左侧的元素都比9小,于是无需移动,把9放到空位中,结果仍为:6,7,9,8,5,1
    *   第三轮:指针指向第四个元素8,此时其左面的元素6,7,9为有序的,将8抽离出来,形成6,7,9,_,5,1,从9开始,依次与8比较,发现8<9,将9向后移,形成6,7,_,9,5,1,8插入到空位中,结果为:6,7,8,9,5,1
    *   第四轮:指针指向第五个元素5,此时其左面的元素6,7,8,9为有序的,将5抽离出来,形成6,7,8,9,_,1,从9开始依次与5比较,发现5比其左侧所有元素都小,5左侧元素全部向右移动,形成_,6,7,8,9,1,将5放入空位,结果5,6,7,8,9,1。
    *   第五轮:同上,1被移到最左面,最后结果:1,5,6,7,8,9。
    */
public static void insertSort() {
    int[] arr = {38, 65, 97, 76, 13, 27, 49};
    // 外层向右的index,即作为比较对象的数据的index
    for (int index = 1; index < arr.length; index++) {
        // 用作比较的数据
        int temp = arr[index];
        int leftindex = index - 1;
        // 当比到最左边或者遇到比temp小的数据时,结束循环
        while (leftindex >= 0 && arr[leftindex] > temp) {
            arr[leftindex + 1] = arr[leftindex];
            leftindex--;
        }
        // 把temp放到空位上
        arr[leftindex + 1] = temp;
    }
    System.out.println(Arrays.toString(arr));
}

二分法排序

二分法是在插入排序的基础上进行了优化
优化点:确定插入的位置进行优化。

插入法是把当前数字和已排序的数据一次比较,二分法是通过折中的方式比较插入点是在左边还是右边,直到确定插入的位置。

[4 5 7 10 29]

//从小到大
public  void sort() {
    for (int i = 1; i < array.length; i++) {
        int temp = array[i];
        int low = 0, high = i - 1;
        int mid = -1;
        // low确定要插入的位置
        while (low <= high) {
            mid = low + (high - low) / 2;
            if (array[mid] > temp) {
                high = mid - 1;
            } else { // 元素相同时,也插入在后面的位置
                low = mid + 1;
            }
        }
        // 把需要移动的元素往后移动一位,给low脚标让出位置
        for(int j = i - 1; j >= low; j--) {
            array[j + 1] = array[j];
        }
        // 把元素插入到low脚标
        array[low] = temp;
    }
}

hash算法

在这里插入图片描述

哈希函数实际上是关键字到内存单元的映射。哈希表(Hash Table)是一种根据关键字直接访问内存存储位置的数据结构。hash算法是不可逆的。

String的hashCode方法,字符对应的二进制码

在这里插入图片描述

MD5算法

加密:https://cmd5.com/hash.aspx?s=123456

解密:https://cmd5.com/

算法原理

因为MD5是单向散列函数,输入任意长度的信息,经过处理,输出为128位的信息;不同的输入得到的不同的结果;根据128位的输出结果不可能反推出输入的信息。所以不能从密文(散列值)反过来得到原文,即没有解密算法。

1、数据填充

对消息进行数据填充,使消息的长度对512取模得448,设消息长度为X,即满足X mod 512=448。根据此公式得出需要填充的数据长度。

填充方法:在消息后面进行填充,填充第一位为1,其余为0。

2、添加消息长度

在第一步结果之后再填充上原消息的长度,可用来进行的存储长度为64位。如果消息长度大于264,则只使用其低64位的值,即(消息长度 对 264取模)。

在此步骤进行完毕后,最终消息长度就是512的整数倍。

3、数据处理

准备需要用到的数据:

4个常数: A = 0x67452301, B = 0x0EFCDAB89, C = 0x98BADCFE, D = 0x10325476;
4个函数:F(X,Y,Z)=(X & Y) | ((~X) & Z); G(X,Y,Z)=(X & Z) | (Y & (~Z)); H(X,Y,Z)=X ^ Y ^ Z; I(X,Y,Z)=Y ^ (X | (~Z));
把消息分以512位为一分组进行处理,每一个分组进行4轮变换,以上面所说4个常数为起始变量进行计算,重新输出4个变量,以这4个变量再进行下一分组的运算,如果已经是最后一个分组,则这4个变量为最后的结果,即MD5值。

MD5算法可以破解么?为什么?网上有在线破解是怎么回事

还有种破解就是采用彩虹表和字典:通过数据库把常见字符转的MD5存储起来为彩虹表,然后直接反查。有两种方法得到字典,一种是日常搜集的用做密码的字符串表,另一种是用排列组合方法生成的,先用MD5程序计算出这些字典项的MD5值,然后再用目标的MD5值在这个字典中检索。

算法数据结构模拟网站

https://visualgo.net/zh/sorting

String str = “44r5t6uutij333224”,求最长的连续不重复字符的子串?

/**
    * String str = "44r5t6uutij333224",求最长的连续不重复字符的子串
    */
@Test
public void testLongestSubstring() {
    String str = "44r5t6uutij333224";
    String longestSubstring = longestSubstring(str);
    log.info(longestSubstring);
}

private String longestSubstring(String str) {
    int[] index = new int[256];
    int begin = 0;
    int end = 0;
    int maxLength = 0;
    for (int i = 0; i < str.length(); i++) {
        char c = str.charAt(i);
        if (index[c] == 0) {
            end++;
        } else {
            if (maxLength < end - begin) {
                maxLength = end - begin;
            }
            begin = index[c] + 1;
        }
        index[c] = i;
    }
    if (maxLength < end - begin) {
        maxLength = end - begin;
    }
    return str.substring(begin, begin + maxLength);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gzh-程序员灿灿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值