剑指Offer之Java算法习题精讲数组查找与字符串交集

剑指Offer之Java算法习题精讲 - 数组查找与字符串交集

一、本章介绍

本章将会对“剑指Offer”系列书籍中有关数组查找与字符串交集的核心算法习题进行总结和分析。我们将会结合具体的算法样例进行讲解,并且会针对其中涉及到的算法思想与编程技巧进行加深细致的探讨。

二、数组查找

1. 二维数组中的查找

题目描述:

在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完整实现一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数,并返回一个 boolean 值。

算法思路:

从矩阵右上角的元素开始,如果该元素等于目标值,则返回 true;如果该元素大于目标值,则剔除该元素所在列;如果该元素小于目标值,则剔除该元素所在行。以此类推,直到找到目标值或到达矩阵边界。

代码示例:

public static boolean findInPartiallySortedMatrix(int[][] matrix, int target) {
    if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
        return false;
    }
    int row = 0;
    int col = matrix[0].length - 1;
    while (row < matrix.length && col >= 0) {
        if (matrix[row][col] == target) {
            return true;
        } else if (matrix[row][col] > target) {
            col--;
        } else {
            row++;
        }
    }
    return false;
}

2. 旋转数组的最小数字

题目描述:

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为旋转。求一个非递减数组的旋转数组的最小数字。例如,数组 {3,4,5,1,2} 为 {1,2,3,4,5} 的一个旋转,该数组的最小值为1。

算法思路:

考虑使用二分查找算法。对于一个排序的数组,使用二分查找算法的时间复杂度为 O(log n)。但是此处的数组是一个旋转数组,因此需要更改查找算法的判断条件。对于一个数组,以最后一个元素为分界点将其分为两个有序的子数组,旋转数组的最小数字即为后半部分的首个元素。每一次查找后,可以通过比较中间元素与区间边界元素的大小来确定需要继续加载左半部分还是右半部分。

代码示例:

public static int minNumberInRotateArray(int[] array) {
    if (array == null || array.length == 0) {
        return 0;
    }
    int left = 0;
    int right = array.length - 1;
    while (left < right) {
        int mid = (left + right) / 2;
        if (array[mid] > array[right]) {
            left = mid + 1;
        } else if (array[mid] == array[right]) {
            right--;
        } else {
            right = mid;
        }
    }
    return array[left];
}

三、字符串交集

1. 字符串排列

题目描述:

输入一个字符串,打印出该字符串中字符的所有排列。例如,输入字符串 abcd,则输出由字符 a、b、c、d 所能排列出来的所有字符串:abcd、abdc、acbd、acdb、adbc、adcb、bacd、badc、bcad、bcda、bdac、bdca、cabd、cadb、cbad、cbda、cdab、cdba、dabc、dacb、dbac、dbca、dcab、dcba。

算法思路:

本题可以使用递归算法解决。固定第一个字符,对剩余字符进行排列。依次枚举第一个字符,再求后面的字符串的排列。当字符串只有一个字符时,其返回值为该字符本身。

代码示例:

public static ArrayList<String> permutation(String string) {
    ArrayList<String> result = new ArrayList<>();
    if (string == null || string.length() == 0) {
        return result;
    }
    char[] chars = string.toCharArray();
    recursion(result, chars, 0);
    Collections.sort(result); // 排序
    return result;
}

private static void recursion(ArrayList<String> result, char[] chars, int i) {
    if (i == chars.length - 1) {
        result.add(String.valueOf(chars));
    } else {
        Set<Character> set = new HashSet<>();
        for (int j = i; j < chars.length; j++) {
            if (!set.contains(chars[j])) {
                set.add(chars[j]);
                swap(chars, i, j);
                recursion(result, chars, i + 1);
                swap(chars, i, j);
            }
        }
    }
}

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

2. 字符串转换成整数

题目描述:

将一个字符串转换成一个整数,该字符串一定表示一个正整数,例如输入字符串 "345",则输出数字 345。

算法思路:

本题可以使用从左到右遍历字符串,累加每个字符对应的数字,最终得到该字符串所表示的整数的值。需要注意参数合法性边界和数字溢出问题。

代码示例:

public static int strToInt(String str) {
    if (str == null || str.length() == 0) {
        return 0;
    }
    int sign = 1; // 标记正负
    int sum = 0; // 累加和
    int i = 0;
    char[] chars = str.toCharArray();
    if (chars[0] == '+' || chars[0] == '-') {
        if (chars[0] == '-') {
            sign = -1;
        }
        i++;
    }
    for (; i < chars.length; i++) {
        // 检查字符是否合法
        if (chars[i] < '0' || chars[i] > '9') {
            return 0;
        }
        // 检查数字是否溢出
        if (sum > Integer.MAX_VALUE / 10 || (sum == Integer.MAX_VALUE / 10 && (chars[i] - '0') > Integer.MAX_VALUE % 10)) {
            return 0;
        }
        sum = sum * 10 + (chars[i] - '0');
    }
    return sign * sum;
}

四、小结

通过本章的学习,我们不仅对数组查找和字符串交集的核心算法有了更为深入的认识,同时也熟悉了在Java中实现各种不同类型算法的代码操作技巧。我们希望这些经验能够为读者在今后的编程实践中提供帮助与指导。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:剑指Offer之Java算法习题精讲数组查找与字符串交集 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • Java 8中的18个常用日期处理(收藏)

    Java 8中的18个常用日期处理(收藏) 介绍 Java 8以前的日期处理方式比较麻烦,Java 8引入了新的日期时间API,也称为JSR-310,使对日期和时间的处理更加简便。本文将介绍Java 8中的18个常用日期处理方法。 1. 获取当天的日期 LocalDate today = LocalDate.now(); 使用LocalDate.now()方…

    Java 2023年5月20日
    00
  • Java 将list集合数据按照时间字段排序的方法

    以下是Java将list集合数据按照时间字段排序的方法的完整攻略。 使用Collections.sort()方法进行排序 Java中可以使用Collections.sort()方法进行排序,我们可以自定义一个Comparator来实现按照时间字段进行排序。Comparator是一个比较器接口,我们需要实现其compare()方法来指定两个元素之间的比较方式。…

    Java 2023年5月20日
    00
  • Java虚拟机之对象创建过程与类加载机制及双亲委派模型

    Java虚拟机之对象创建过程 Java中的对象在内存中的实现是由Java虚拟机(JVM)负责完成的。对象的创建过程分为三步: 分配内存空间:JVM为对象在堆内存中分配一块连续的内存空间。 初始化对象:JVM为对象的成员变量赋初始值。 调用构造函数:JVM调用对象的构造函数来完成对象的初始化。 例子说明 public class Person { privat…

    Java 2023年5月26日
    00
  • Java中ShardingSphere 数据分片的实现

    非常感谢您对“Java中ShardingSphere 数据分片的实现”的关注。下面是大致的攻略: 1. 什么是ShardingSphere ShardingSphere是一个开源的分布式数据库中间件解决方案,提供数据库分片、分布式事务、数据治理等功能。它由Apache ShardingSphere孵化经过一年多的孵化过程,于2021年2月正式成为Apache…

    Java 2023年5月20日
    00
  • java实现文件拷贝的七种方式

    我来为你讲解“Java实现文件拷贝的七种方式”的攻略。以下是这七种方式: 1. 使用字节流(InputStream和OutputStream)进行拷贝 字节流是Java I/O中的基本类,可以方便地进行文件拷贝。我们可以使用 FileInputStream 读取源文件,将数据写入 FileOutputStream 中实现文件拷贝。具体代码如下: public…

    Java 2023年5月20日
    00
  • 支持IE和firefox的js代码美化加亮源码

    首先,我们需要了解什么是代码美化加亮。代码美化加亮是通过对代码进行格式化和着色,使代码看起来更加美观、易读和可维护的技术。在项目开发中,我们常常需要对JS代码进行美化加亮,以便于代码的审查、调试和维护。 操作步骤: 1.选择一个JS代码美化工具,并下载相关工具。本例中我们选择支持IE和Firefox的CodeMirror代码编辑器。2.引入jQuery和Co…

    Java 2023年6月15日
    00
  • java map转Multipart/form-data类型body实例

    下面是java map转Multipart/form-data类型body的详细攻略: 创建一个MultiPart对象 在将Map类型转换成Multipart/form-data类型之前,我们需要先创建一个MultiPart对象作为容器,并传入Content-Type为multipart/form-data的Header。 MultiPart multiPa…

    Java 2023年5月20日
    00
  • jdk安装、Java环境配置方法详解

    JDK安装、Java环境配置方法详解 什么是JDK? Java Development Kit(JDK)是一个开发环境,它允许开发人员创建Java应用程序并将其部署到不同的运行环境中,例如桌面和服务器。 JDK包含Java Runtime Environment(JRE)以及开发人员需要创建Java应用程序和Applet的工具。 JDK安装步骤 下载JDK安…

    Java 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部