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

Java面试黄金宝典23

1. 手写 KMP 算法

  • 定义

KMP(Knuth - Morris - Pratt)算法是一种高效的字符串匹配算法。它通过预处理模式串,构建一个部分匹配表(也称为最长前缀后缀表),利用已匹配的信息,避免在匹配过程中进行不必要的回溯,从而提高匹配效率。

  • 要点
  1. 构建部分匹配表(LPS 表),记录模式串中每个位置之前的子串的最长公共前后缀长度。
  2. 在匹配过程中,当发生不匹配时,根据 LPS 表移动模式串的位置,避免从头开始匹配。

代码示例

java

public class KMP {
    public static int kmpSearch(String text, String pattern) {
        int[] lps = computeLPSArray(pattern);
        int i = 0;
        int j = 0;
        while (i < text.length()) {
            if (pattern.charAt(j) == text.charAt(i)) {
                j++;
                i++;
            }
            if (j == pattern.length()) {
                return i - j;
            } else if (i < text.length() && pattern.charAt(j) != text.charAt(i)) {
                if (j != 0) {
                    j = lps[j - 1];
                } else {
                    i++;
                }
            }
        }
        return -1;
    }

    private static int[] computeLPSArray(String pattern) {
        int[] lps = new int[pattern.length()];
        int len = 0;
        int i = 1;
        lps[0] = 0;
        while (i < pattern.length()) {
            if (pattern.charAt(i) == pattern.charAt(len)) {
                len++;
                lps[i] = len;
                i++;
            } else {
                if (len != 0) {
                    len = lps[len - 1];
                } else {
                    lps[i] = 0;
                    i++;
                }
            }
        }
        return lps;
    }

    public static void main(String[] args) {
        String text = "ABABDABACDABABCABAB";
        String pattern = "ABABCABAB";
        int index = kmpSearch(text, pattern);
        System.out.println("Pattern found at index: " + index);
    }
}

  • 应用
  1. 文本编辑器中的查找功能:在大文本中快速查找特定的字符串。
  2. 生物信息学:在 DNA 序列中查找特定的基因片段。
  3. 网络爬虫:在网页内容中查找特定的关键词。

2. 对一个基本有序的数组应该采用什么方式进行排序,对一个乱序的数组应该采用什么方式排序能快速找到前 n 个数?为什么?

  • 基本有序数组排序

排序方式及定义

采用插入排序。插入排序是一种简单直观的排序算法,它的工作原理是将未排序的数据插入到已排序序列的合适位置。

  • 原因

对于基本有序的数组,插入排序只需要进行少量的比较和移动操作。因为大部分元素已经处于正确的位置,每次插入新元素时,只需要移动少数几个元素,所以时间复杂度接近 O(n)。

  • 要点

每次将一个未排序的元素插入到已排序序列的合适位置。

乱序数组找前 n 个数

  • 排序方式及定义

采用堆排序。堆排序是利用堆这种数据结构所设计的一种排序算法,它可以在 O(nlogk) 的时间复杂度内找到前 k 大(或前 k 小)的数。

  • 原因

通过构建一个大小为 k 的最小堆(或最大堆),遍历数组,将元素与堆顶元素比较,若满足条件则替换堆顶元素并调整堆。这样可以在不将整个数组排序的情况下,快速找到前 k 个元素。

  • 要点

构建堆和调整堆的操作。

3. 给定一个数组,里面放置任意数量的随机数,如何快速统计出数组中重复的数字以及出现次数

  • 定义

使用哈希表(如 HashMap)来统计数组中每个数字的出现次数。哈希表是一种根据键值对存储数据的数据结构,通过哈希函数将键映射到存储位置,从而实现快速的查找和插入操作。

  • 要点
  1. 使用哈希表存储数字和出现次数。
  2. 遍历数组更新哈希表。

代码示例

java

import java.util.HashMap;
import java.util.Map;

public class CountDuplicates {
    public static void main(String[] args) {
        int[] arr = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
        Map<Integer, Integer> countMap = new HashMap<>();
        for (int num : arr) {
            countMap.put(num, countMap.getOrDefault(num, 0) + 1);
        }
        for (Map.Entry<Integer, Integer> entry : countMap.entrySet()) {
            if (entry.getValue() > 1) {
                System.out.println("Number: " + entry.getKey() + ", Count: " + entry.getValue());
            }
        }
    }
}

  • 应用
  1. 数据去重:在处理大量数据时,统计重复数据的出现次数,以便进行去重操作。
  2. 频率分析:在文本处理中,统计单词的出现频率。

4. 给定字母集合 (a - z),求出由集合中这些字母组成的所有非空子集

  • 定义

使用位运算来生成所有子集。对于一个包含 n 个元素的集合,它的子集个数为 2n。可以通过遍历从 1 到 2n−1 的所有整数,每个整数的二进制表示对应一个子集。

  • 要点
  1. 使用位运算判断每个元素是否在子集中。
  2. 遍历所有可能的子集。

代码示例

java

import java.util.ArrayList;
import java.util.List;

public class Subsets {
    public static List<List<Character>> getAllSubsets() {
        List<List<Character>> subsets = new ArrayList<>();
        char[] letters = new char[26];
        for (int i = 0; i < 26; i++) {
            letters[i] = (char) ('a' + i);
        }
        int n = letters.length;
        for (int i = 1; i < (1 << n); i++) {
            List<Character> subset = new ArrayList<>();
            for (int j = 0; j < n; j++) {
                if ((i & (1 << j)) != 0) {
                    subset.add(letters[j]);
                }
            }
            subsets.add(subset);
        }
        return subsets;
    }

    public static void main(String[] args) {
        List<List<Character>> subsets = getAllSubsets();
        for (List<Character> subset : subsets) {
            System.out.println(subset);
        }
    }
}

  • 应用
  1. 组合优化问题:在求解组合优化问题时,需要枚举所有可能的组合,子集生成算法可以用于生成所有可能的组合。
  2. 密码学:在密码学中,需要生成所有可能的密钥组合,子集生成算法可以用于生成密钥空间。

5. 用 5 行代码实现字符个数统计

  • 定义

使用 HashMap 统计字符串中每个字符的出现次数。HashMap 是 Java 中的一种哈希表实现,它可以快速地存储和查找键值对。

代码示例

java

import java.util.HashMap;
import java.util.Map;

public class CharacterCount {
    public static void main(String[] args) {
        String str = "hello world";
        Map<Character, Integer> countMap = new HashMap<>();
        for (char c : str.toCharArray()) {
            countMap.put(c, countMap.getOrDefault(c, 0) + 1);
        }
        System.out.println(countMap);
    }
}

  • 应用
  1. 文本分析:统计文本中每个字符的出现频率,用于分析文本的特征。
  2. 数据压缩:根据字符的出现频率进行编码,实现数据压缩。

6. 如何反转单链表

  • 定义

反转单链表是将链表中节点的指针方向反转,使得原来的头节点变成尾节点,原来的尾节点变成头节点。可以使用迭代或递归的方式实现。

  • 要点
  1. 迭代方法:需要记录前一个节点和当前节点,在遍历链表的过程中,将当前节点的 next 指针指向前一个节点。
  2. 递归方法:先递归地反转后续节点,再将当前节点的 next 指针指向前一个节点,需要注意递归的终止条件。

迭代代码示例

java

class ListNode {
    int val;
    ListNode next;
    ListNode(int val) {
        this.val = val;
    }
}

public class ReverseLinkedList {
    public static ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode curr = head;
        while (curr != null) {
            ListNode nextTemp = curr.next;
            curr.next = prev;
            prev = curr;
            curr = nextTemp;
        }
        return prev;
    }

    public static void main(String[] args) {
        ListNode head = new ListNode(1);
        head.next = new ListNode(2);
        head.next.next = new ListNode(3);
        ListNode reversedHead = reverseList(head);
        while (reversedHead != null) {
            System.out.print(reversedHead.val + " ");
            reversedHead = reversedHead.next;
        }
    }
}

递归代码示例

java

class ListNode {
    int val;
    ListNode next;
    ListNode(int val) {
        this.val = val;
    }
}

public class ReverseLinkedListRecursive {
    public static ListNode reverseList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode p = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return p;
    }

    public static void main(String[] args) {
        ListNode head = new ListNode(1);
        head.next = new ListNode(2);
        head.next.next = new ListNode(3);
        ListNode reversedHead = reverseList(head);
        while (reversedHead != null) {
            System.out.print(reversedHead.val + " ");
            reversedHead = reversedHead.next;
        }
    }
}

  • 应用
  1. 链表操作:在链表的各种操作中,反转链表是一个基本的操作,常用于解决其他链表相关的问题。
  2. 数据处理:在某些数据处理场景中,需要对链表进行反转操作。

7. 如何实现快速排序,快速排序的时间复杂度为什么是 O(nlogn)

  • 定义

快速排序是一种基于分治法的排序算法。它选择一个基准元素,将数组分为两部分,使得左边部分的元素都小于等于基准元素,右边部分的元素都大于等于基准元素,然后递归地对左右两部分进行排序。

  • 要点
  1. 选择基准元素。
  2. 分区操作,将数组分为两部分。
  3. 递归排序左右两部分。

代码示例

java

public class QuickSort {
    public static void quickSort(int[] arr, int low, int high) {
        if (low < high) {
            int pi = partition(arr, low, high);
            quickSort(arr, low, pi - 1);
            quickSort(arr, pi + 1, high);
        }
    }

    private static int partition(int[] arr, int low, int high) {
        int pivot = arr[high];
        int i = low - 1;
        for (int j = low; j < high; j++) {
            if (arr[j] <= pivot) {
                i++;
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
        int temp = arr[i + 1];
        arr[i + 1] = arr[high];
        arr[high] = temp;
        return i + 1;
    }

    public static void main(String[] args) {
        int[] arr = {10, 7, 8, 9, 1, 5};
        quickSort(arr, 0, arr.length - 1);
        for (int num : arr) {
            System.out.print(num + " ");
        }
    }
}

时间复杂度分析

快速排序的平均时间复杂度是 O(nlogn)。在每次分区操作中,需要遍历数组一次,时间复杂度为 O(n)。而递归的深度平均为 logn,因为每次分区都将数组大致分为两部分。因此,总的时间复杂度为 O(nlogn)。

  • 应用
  1. 大规模数据排序:快速排序在平均情况下具有较高的效率,适用于大规模数据的排序。
  2. 编程语言的内置排序函数:很多编程语言的内置排序函数都采用了快速排序或其变种。

8. 如何实现并发场景下的多线程代码

  • 定义

在 Java 中,可以通过继承 Thread 类或实现 Runnable 接口来创建线程。使用 synchronized 关键字或 Lock 接口来实现线程同步,避免多个线程同时访问共享资源导致的数据不一致问题。

  • 要点
  1. 创建线程的两种方式:继承 Thread 类和实现 Runnable 接口。
  2. 线程同步的方法:synchronized 关键字和 Lock 接口。

代码示例

java

class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}

class MyRunnable implements Runnable {
    private Counter counter;

    public MyRunnable(Counter counter) {
        this.counter = counter;
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            counter.increment();
        }
    }
}

public class MultiThreadingExample {
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();
        Thread t1 = new Thread(new MyRunnable(counter));
        Thread t2 = new Thread(new MyRunnable(counter));
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("Final count: " + counter.getCount());
    }
}

  • 应用
  1. 服务器端编程:在服务器端处理多个客户端请求时,使用多线程可以提高服务器的并发处理能力。
  2. 并行计算:在需要进行大量计算的场景中,使用多线程可以将计算任务分配到多个线程中并行执行,提高计算效率。

9. 一个数组里的数据只有一个是 3 个相同的,其他都是两个相同 怎么找出这个数

  • 定义

使用哈希表统计每个数字的出现次数,然后遍历哈希表,找出出现次数为 3 的数字。

  • 要点
  1. 使用哈希表存储数字和出现次数。
  2. 遍历哈希表找出出现次数为 3 的数字。

代码示例

java

import java.util.HashMap;
import java.util.Map;

public class FindTripleNumber {
    public static int findTriple(int[] arr) {
        Map<Integer, Integer> countMap = new HashMap<>();
        for (int num : arr) {
            countMap.put(num, countMap.getOrDefault(num, 0) + 1);
        }
        for (Map.Entry<Integer, Integer> entry : countMap.entrySet()) {
            if (entry.getValue() == 3) {
                return entry.getKey();
            }
        }
        return -1;
    }

    public static void main(String[] args) {
        int[] arr = {1, 1, 2, 2, 3, 3, 3, 4, 4};
        int triple = findTriple(arr);
        System.out.println("The number that appears three times is: " + triple);
    }
}

  • 应用
  1. 数据错误检测:在数据处理过程中,检测数据中是否存在异常的重复次数。
  2. 密码学:在密码学中,通过统计字符的出现次数来检测密码的安全性。

10. 如何实现字符转 int 型,需要考虑负数,异常等问题

  • 定义

遍历字符串,将每个字符转换为数字,然后根据正负号计算最终的整数。需要处理输入为空、包含非数字字符等异常情况。

  • 要点
  1. 处理正负号。
  2. 处理非数字字符。
  3. 处理溢出问题。

代码示例

java

public class StringToInt {
    public static int myAtoi(String str) {
        str = str.trim();
        if (str.length() == 0) {
            return 0;
        }
        int sign = 1;
        int index = 0;
        if (str.charAt(0) == '-') {
            sign = -1;
            index++;
        } else if (str.charAt(0) == '+') {
            index++;
        }
        long result = 0;
        while (index < str.length() && Character.isDigit(str.charAt(index))) {
            int digit = str.charAt(index) - '0';
            result = result * 10 + digit;
            if (sign == 1 && result > Integer.MAX_VALUE) {
                return Integer.MAX_VALUE;
            }
            if (sign == -1 && -result < Integer.MIN_VALUE) {
                return Integer.MIN_VALUE;
            }
            index++;
        }
        return (int) (sign * result);
    }

    public static void main(String[] args) {
        String str = "-123";
        int num = myAtoi(str);
        System.out.println("Converted number: " + num);
    }
}

  • 应用
  1. 数据输入处理:在处理用户输入时,需要将字符串类型的数字转换为整数类型。
  2. 文件读取:在读取文件中的数字数据时,需要将字符串形式的数字转换为整数。

 友情提示:本文已经整理成文档,可以到如下链接免积分下载阅读

https://download.csdn.net/download/ylfhpy/90548891

相关文章:

  • 鸿蒙ArkTS开发:微信/系统来电通话监听功能实现
  • pycharm-qt56pyside-常用控件
  • Dubbo 框架内置的并发控制策略
  • Maven:Java项目构建与依赖管理工具
  • 解释Node.js,Node.js环境
  • 数据结构每日一题day7(顺序表)★★★★★
  • WEB安全--RCE--RCE的绕过
  • 网络深处的守门人
  • 马达加斯加企鹅字幕
  • 网站安全专栏-------DDOS常见的解决办法和防范措施
  • Vue 3 模板引用(Template Refs)详解与实战示例
  • Redis-06.Redis常用命令-列表操作命令
  • Zookeeper中的Zxid是如何设计的
  • leetcode144.二叉树展开为链表
  • Linux SCP传输文件免密配置
  • 硕士毕设-语义分割-4-通过grounding-sam生成效果很好的pesudo
  • 【图论】最短路径问题总结
  • 伴伴租赁系统-物品售卖-二手回收-物品租赁-支持微信/支付宝小程序/app/h5
  • 通过Spring Boot集成WebSocket进行消息通信
  • Java开发者指南:深入理解HotStuff新型共识算法
  • 有没有专门做图的网站/百度查一下
  • 启迪网站建设/湖南网站托管
  • 做视频网站用哪个模板/百度开户多少钱
  • 用什么软件可以做网站/seo排名赚下载
  • 珠海企业集团网站建设/百度查询关键词排名工具
  • 拉萨网站建设系统/软文推广代理平台