Java入门高频考查算法逻辑基础知识3-编程篇(超详细18题1.8万字参考编程实现)

本文涉及的产品
云原生网关 MSE Higress,422元/月
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
应用实时监控服务-用户体验监控,每月100OCU免费额度
简介: 解决这类问题时,建议采取下面的步骤:理解数学原理:确保你懂得基本的数学公式和法则,这对于制定解决方案至关重要。优化算法:了解时间复杂度和空间复杂度,并寻找优化的机会。特别注意避免不必要的重复计算。代码实践:多编写实践代码,并确保你的代码是高效、清晰且稳健的。错误检查和测试:要为你的代码编写测试案例,测试标准的、边缘情况以及异常输入。进行复杂问题简化:面对复杂的问题时,先尝试简化问题,然后逐步分析和解决。沟通和解释:在编写代码的时候清晰地沟通你的思路,不仅要写出正确的代码,还要能向面试官解释你的

准备这些面试题时,请考虑如下准备步骤:

  • 理解问题并澄清任何可能的疑点。确保你了解了面试官的期望,包括问题限制条件和期望的解决方案。
  • 如果可能且适用的话,尝试先给出一个简单的解决方案,比如暴力法,然后再逐步优化它。
  • 在优化之前,先分析暴力解法的效率,了解它的时间和空间复杂度,然后解释为什么需要更有效的解法。
  • 采取逐步的方法首先解决小规模问题,再逐渐递进到大规模问题。
  • 编写清晰、易读的代码,并在写代码的同时解释你的思路。
  • 一旦代码完成,测试它并讨论可能的边界情况或错误,以及如何检测和修复这些错误。
  • 最后,讲解代码的时间和空间复杂度,并在有可能的情况下提供优化方案。

       

准备解决这类问题时,建议采取下面的步骤:

  • 理解数学原理:确保你懂得基本的数学公式和法则,这对于制定解决方案至关重要。
  • 优化算法:了解时间复杂度和空间复杂度,并寻找优化的机会。特别注意避免不必要的重复计算。
  • 代码实践:多编写实践代码,并确保你的代码是高效、清晰且稳健的。
  • 错误检查和测试:要为你的代码编写测试案例,测试标准的、边缘情况以及异常输入。
  • 进行复杂问题简化:面对复杂的问题时,先尝试简化问题,然后逐步分析和解决。
  • 沟通和解释:在编写代码的时候清晰地沟通你的思路,不仅要写出正确的代码,还要能向面试官解释你的解决方案。
  • 考虑可维护性:在真实工作中,代码的可维护性和可读性非常重要,因此在面试中编写易于理解和维护的代码也很关键。


一、实现Math.pow()方法

Math.pow()方法:

   Math.pow() 方法是 Java 中的一个数学函数,它用于计算一个数的指定次幂。该方法接受两个参数:底数(base)和指数(exponent),并返回底数的指定次幂的结果。

方法签名:

public static double pow(double base, double exponent)
image.gif

参数说明:

  • base:指定底数,即要进行幂运算的数字。
  • exponent:指定指数,即要进行幂运算的次数。

返回结果:

  • 返回一个 double 类型的值,表示底数的指定次幂的结果。

示例用法:

double result = Math.pow(2, 3); // 计算 2 的 3 次幂,结果为 8.0
image.gif

       需要注意的是,Math.pow() 方法的返回值类型是 double,即使指数为整数,结果也会是浮点数。如果需要将结果转换为整数,可以使用强制类型转换或者使用 Math.round() 方法进行四舍五入。

int result = (int) Math.pow(2, 3); // 将结果转换为整数,结果为 8
int roundedResult = Math.round((float) Math.pow(2, 3)); // 将结果四舍五入为整数,结果为 8
image.gif

       在进行幂运算时,需要考虑边界条件,如底数为 0 且指数为负数的情况,根据实际需求进行错误处理。

编程实现:

       在 Java 编程中,可以通过使用循环递归的方式实现类似于 Math.pow() 的功能,它用于计算一个数字的指定次幂。

       使用循环实现 Math.pow() 方法可以如下所示:

public class PowerCalculator {
    public static double power(double base, int exponent) {
        if (exponent == 0) {
            return 1.0;
        }
        
        double result = 1.0;
        int absExponent = Math.abs(exponent);
        
        for (int i = 1; i <= absExponent; i++) {
            result *= base;
        }
        
        return exponent < 0 ? 1.0 / result : result;
    }
}
image.gif

       使用递归实现 Math.pow() 方法可以如下所示:

public class PowerCalculator {
    public static double power(double base, int exponent) {
        if (exponent == 0) {
            return 1.0;
        }
        
        if (exponent < 0) {
            return 1.0 / power(base, -exponent);
        }
        
        if (exponent % 2 == 0) {
            double temp = power(base, exponent / 2);
            return temp * temp;
        } else {
            return base * power(base, exponent - 1);
        }
    }
}
image.gif

       以上代码是一个简单的实现示例,注意需要考虑指数为负数的情况和迭代的边界条件。要根据实际需求和代码规范进行适当的修改和优化。

       

二、实现二分搜索

       二分搜索,也称为二分查找,是一种高效的搜索算法,用于在有序数组或列表中查找特定元素。

       以下是一个使用 Java 编程实现二分搜索的示例:

public class BinarySearch {
    public static int binarySearch(int[] arr, int target) {
        int left = 0;
        int right = arr.length - 1;
        
        while (left <= right) {
            int mid = left + (right - left) / 2;
            
            if (arr[mid] == target) {
                return mid;
            }
            
            if (arr[mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        
        return -1;
    }
    
    public static void main(String[] args) {
        int[] arr = {1, 3, 5, 7, 9, 11, 13};
        int target = 7;
        int result = binarySearch(arr, target);
        
        if (result == -1) {
            System.out.println("Element not found");
        } else {
            System.out.println("Element found at index " + result);
        }
    }
}
image.gif

       在上述示例中,我们定义了一个 binarySearch 方法来执行二分搜索。该方法接收一个有序数组 arr 和目标值 target 作为参数。

       在二分搜索中,我们使用两个指针 leftright 分别指向数组的最左边和最右边。在每一次迭代中,我们计算中间索引 mid,并将目标元素与 arr[mid] 进行比较。

  • 如果 arr[mid] 等于目标值 target,则找到了目标元素,返回 mid
  • 如果 arr[mid] 小于目标值 target,则目标值可能在 mid 的右侧,更新左指针 leftmid + 1
  • 如果 arr[mid] 大于目标值 target,则目标值可能在 mid 的左侧,更新右指针 rightmid - 1

       重复以上步骤直到找到目标元素或确定目标元素不存在(即 left 大于 right),此时返回 -1。

       在主函数中,我们创建了一个有序数组 arr,并以目标值 target 为参数调用 binarySearch 方法进行搜索。根据返回的结果,我们输出相应的提示信息。

       

三、实现迭代法

       迭代法是一种通过多次迭代逐渐逼近问题的解的方法。它通常通过在每一次迭代中更新变量的值,直到满足某个终止条件来求解问题。

       下面是一个使用 Java 编程实现迭代法的示例,用于求解一个方程的根:

public class Iteration {
    public static double solveEquation(double x) {
        double epsilon = 1e-6; // 终止条件:解的相对误差小于 epsilon
        double guess = x; // 初始猜测值
        
        while (Math.abs(guess * guess - x) > epsilon) {
            guess = (guess + x / guess) / 2; // 更新猜测值
        }
        
        return guess; // 返回逼近的解
    }
    
    public static void main(String[] args) {
        double x = 16;
        double result = solveEquation(x);
        System.out.println("The square root of " + x + " is: " + result);
    }
}
image.gif

       在上述示例中,我们定义了一个 solveEquation 方法来求解方程的根。我们使用牛顿迭代法来逼近方程 guess * guess = x 的解。

       在每一次迭代中,我们通过更新猜测值 guess 来逼近解。具体来说,我们使用公式 (guess + x / guess) / 2 来更新猜测值,直到解的相对误差小于设定的终止条件 epsilon

       在主函数中,我们调用 solveEquation 方法来求解方程 guess * guess = x 的根,并输出结果。

       需要注意的是,迭代法是一种通用的方法,可以用于解决各种问题,不仅仅局限于方程求根。根据具体的问题,你可能需要修改迭代的终止条件和更新规则来适应不同的应用场景。

       

四、实现快速幂算法

       下面是一个使用 Java 编程实现快速幂算法的示例:

public class FastPower {
    public static double fastPower(double base, int exponent) {
        if (exponent < 0) {
            base = 1 / base;
            exponent = -exponent;
        }
        double result = 1.0;
        while (exponent > 0) {
            if (exponent % 2 == 1) {
                result *= base;
            }
            base *= base;
            exponent /= 2;
        }
        return result;
    }
    public static void main(String[] args) {
        double base = 2.0;
        int exponent = 10;
        double result = fastPower(base, exponent);
        System.out.println(base + " raised to the power of " + exponent + " is: " + result);
    }
}
image.gif

       在上述示例中,我们定义了一个 fastPower 方法,用于计算一个实数 base 的整数次幂。在该方法中,我们使用快速幂算法来进行高效的指数计算。

       具体而言,我们使用迭代的方式计算 baseexponent 次幂。在每一次迭代中,我们将 exponent 视作二进制数,通过位运算的方式来进行计算,从而减少了计算的次数。

       在主函数中,我们以 base 为底,exponent 为指数调用 fastPower 方法进行计算,并输出结果。

       快速幂算法的关键是将指数 exponent 表示为二进制形式,并利用位运算的特性来降低计算复杂度,从而实现快速的幂次计算。

       

五、实现浮点数精度问题

       在计算机中,浮点数精度问题是由于浮点数的有限位数表示导致的问题,可能会出现舍入误差和精度损失。在实际编程中,可以通过以下方式来处理浮点数精度问题:

       1. 使用BigDecimal类:对于需要高精度计算的场景,可以使用 Java 中的 BigDecimal 类。BigDecimal 提供了任意精度的定点数表示和操作,可以有效避免浮点数精度问题。

import java.math.BigDecimal;
public class PrecisionIssue {
    public static void main(String[] args) {
        BigDecimal num1 = new BigDecimal("0.1");
        BigDecimal num2 = new BigDecimal("0.2");
        BigDecimal sum = num1.add(num2);
        System.out.println("Sum: " + sum);
    }
}
image.gif

       2. 比较浮点数:在比较浮点数时,避免直接使用 == 来进行比较,而是考虑使用一个很小的误差范围,或者检查它们的差值是否在某个特定范围内。

public class CompareFloats {
    public static void main(String[] args) {
        double num1 = 0.1 + 0.2;
        double num2 = 0.3;
        double epsilon = 1e-10; // 定义一个很小的误差范围
        if (Math.abs(num1 - num2) < epsilon) {
            System.out.println("num1 and num2 接近相等");
        } else {
            System.out.println("num1 和 num2 不相等");
        }
    }
}
image.gif

       3. 注意精度丢失:在进行浮点数计算时,要注意可能的精度丢失,尤其是在连续的浮点数计算中。可以通过合理的算法设计来减少精度损失,或者在需要高精度计算时选择合适的数据类型。

       

六、实现避免整数溢出问题

       在编程中,避免整数溢出问题是非常重要的,特别是在处理大数值时。以下是一些常见的方法用于避免整数溢出问题:

       1. 使用长整型:对于需要处理较大整数的情况,可以选择使用长整型(long),它的取值范围更大,可以避免一些整数溢出问题。

public class AvoidIntegerOverflow {
    public static void main(String[] args) {
        long num1 = 2147483648L; // 使用L后缀声明长整型常量
        long num2 = 2147483647L;
        long sum = num1 + num2;
        System.out.println("Sum: " + sum);
    }
}
image.gif

       2. 类型转换和范围检查:在进行类型转换时,要仔细检查目标类型的取值范围,避免转换后超出范围。需要特别注意整数相乘和相加操作可能导致溢出,所以要在进行这些操作前进行范围检查。

       3. 使用BigInteger类:对于需要处理超大整数的情况,可以使用 Java的 BigInteger 类,它提供了任意精度的整数操作,可以避免整数溢出问题。

import java.math.BigInteger;
public class AvoidIntegerOverflow {
    public static void main(String[] args) {
        BigInteger num1 = new BigInteger("12345678901234567890");
        BigInteger num2 = new BigInteger("98765432109876543210");
        BigInteger product = num1.multiply(num2);
        System.out.println("Product: " + product);
    }
}
image.gif

       4. 注意算术运算:在进行整数加减乘除运算时,务必注意运算结果的范围,尤其是在循环或递归计算中,要及时进行范围检查并采取相应的处理方法,比如使用长整型或者BigInteger类。

       

七、实现最小二乘法

       当使用 Java 进行最小二乘法实现时,可以使用 Apache Commons Math 库来进行线性回归计算。以下是一个使用 Apache Commons Math 实现最小二乘法的示例代码:

import org.apache.commons.math3.fitting.PolynomialCurveFitter;
import org.apache.commons.math3.fitting.WeightedObservedPoints;
import org.apache.commons.math3.fitting.WeightedObservedPoint;
public class LinearRegressionExample {
    public static void main(String[] args) {
        WeightedObservedPoints points = new WeightedObservedPoints();
        
        // 构造输入数据
        points.add(0, 1);
        points.add(1, 3);
        points.add(2, 7);
        points.add(3, 13);
        points.add(4, 21);
        points.add(5, 31);
        
        // 使用最小二乘法拟合线性模型
        PolynomialCurveFitter fitter = PolynomialCurveFitter.create(1); // 1 代表一次线性模型
        double[] coeff = fitter.fit(points.toList());
        
        // 输出拟合的线性模型参数
        double m = coeff[1]; // 斜率
        double c = coeff[0]; // 截距
        System.out.println("斜率 m: " + m);
        System.out.println("截距 c: " + c);
    }
}
image.gif

       在这个示例中,我们使用了 Apache Commons Math 库的 PolynomialCurveFitterWeightedObservedPoints 类。首先, 我们将输入数据添加到 WeightedObservedPoints 对象中,然后使用 PolynomialCurveFitter 进行一次线性模型的拟合。得到的 coeff 数组包含了截距和斜率。

       需要注意的是,为了运行以上的代码,需要在项目中包含 Apache Commons Math 库的 JAR 文件。

这是一个简单的演示,实际应用中可能需要处理更复杂的数据和模型,以及结果的解释和验证。

       

八、实现大整数的指数计算

       在Java中,可以使用BigInteger类来进行大整数的指数计算。BigInteger类提供了支持大整数运算的方法,包括指数计算。

重要的是要注意,BigIntegerpow方法接受的指数是一个int类型的值。这意味着指数的大小还是有限的,但底数本身可以是任意大的。BigInteger提供的方法会自动处理数字的存储和运算,避免了溢出的问题。

       如果你需要进行的指数计算的结果比较大,直接使用BigIntegerpow方法可能会导致内存不足的错误,因为BigInteger对象会试图存储运算结果的所有位。然而,这不是溢出,而是由于大数运算需要消耗的内存空间超出了JVM为应用程序分配的内存。

       下面我将示范如何使用BigInteger类来实现指数计算:

import java.math.BigInteger;
public class BigIntegerExponentiation {
    public static void main(String[] args) {
        BigInteger base = new BigInteger("2");
        int exponent = 1000; // 指数为1000,非常大的数
        try {
            // 大整数的指数计算
            BigInteger result = base.pow(exponent);
            
            // 输出结果
            System.out.println(base + " raised to the power of " + exponent + " is :\n" + result);
        } catch (ArithmeticException ex) {
            // 捕获异常,并打印异常信息
            System.err.println("ArithmeticException: " + ex.getMessage());
        }
    }
}
image.gif

       在这个示例中,由于BigInteger的设计目的是处理任意大小的整数,所以它自身方法已经进行了大数溢出的处理。你不需要担心像基本数据类型那样的数值溢出问题。但是,你仍然需要处理潜在的OutOfMemoryError,这可能发生在极端情况下,当你的计算结果超出了JVM可分配的最大内存。

       如果你预计你将处理极其庞大的数值,可能需要考虑优化你的算法,或者提前检查指数大小以避免不合理的计算。例如,在实际情况中,要对非常大的数字进行高次方的指数运算是不切实际的,因为其结果将是非常巨大的。

       最重要的是,BigInteger类的运算方法都是以一种方式实现的,它们会在发生溢出时提供数学上正确的结果,或者抛出异常来表明某种形式的错误。在执行BigInteger运算时,你不需要担心传统意义上的溢出,因为任何单个BigInteger都可以表示任意大的数字(受限于内存)。

       

九、实现二分对数运算

       Java中的Math.log:

   Math.log 函数用于计算以自然常数 e 为底的对数。这个函数的用法与 JavaScript 中的类似,接受一个参数并返回以 e 为底的对数值。

double result = Math.log(x);
image.gif

       其中 x 是要计算对数的值,返回的结果是 x 的自然对数。举个例子,Math.log(1) 的结果是 0,因为任何数以自身为底的对数都是 1;而 Math.log(Math.E) 的结果将等于 1,因为 e^1 等于 e;Math.log(10) 的结果约等于 2.302,因为 e^2.302 约等于 10。

这个函数在处理数学和科学计算时非常有用。希望这可以帮助你理解 Java 中的 Math.log 函数!

       

       用Math.log实现:

       在Java中,可以使用Math类的log方法来实现二分对数运算。该方法接受两个参数,一个是底数,另一个是指数。它返回以指定底数为底、指定指数的对数。

       以下是一个示例代码,演示如何使用Math类的log方法进行二分对数运算:

public class BinaryLogarithm {
    public static void main(String[] args) {
        double base = 2;
        double number = 8;
        // 进行二分对数运算
        double result = Math.log(number) / Math.log(base);
        // 输出结果
        System.out.println(result);
    }
}
image.gif

       在这个示例中,我们使用底数2和数字8进行二分对数运算。首先,我们计算以e为底、number的自然对数(即ln(number))。然后,我们计算以e为底,底数为base的自然对数(即ln(base))。最后,我们将这两个结果相除得到最终的结果,也就是以指定底数为底、指定数字的对数。

       需要注意的是,Math类的log方法返回的是以e为底的自然对数。为了得到以其他底数为底的对数,我们需要使用换底公式,将底数为e的对数转换为以任意底数的对数。具体实现就是将以e为底的对数除以以指定底数为底的对数。在这个示例中,我们使用Math.log(number)获取以e为底、指定数字的自然对数,然后将其除以Math.log(base)获取以指定底数为底的对数。

       这样就可以使用Java中的Math类来实现二分对数运算。需要注意的是,Math类的log方法返回的是一个double类型的数值,对结果进行舍入或转换,以满足你的特定需求。

       

       不用Math.log实现:

       使用循环和二分法来实现二分对数运算。以下是使用二分法来计算二分对数的示例代码:

public class BinaryLogarithm {
    public static void main(String[] args) {
        double base = 2;
        double number = 8;
        // 进行二分对数运算
        double result = binaryLogarithm(base, number);
        // 输出结果
        System.out.println(result);
    }
    public static double binaryLogarithm(double base, double number) {
        double low = 0;   // 最小范围
        double high = number;  // 最大范围
        double precision = 0.00000001;  // 精度,即最小差距
        double mid;
        // 通过二分法逼近对数值
        while (high - low > precision) {
            mid = (low + high) / 2;  // 计算中间值
            double calculated = Math.pow(base, mid);  // 计算以base为底、mid的指数幂
            if (calculated < number) {
                low = mid;   // 缩小范围到中间值和高值之间
            } else {
                high = mid;  // 缩小范围到低值和中间值之间
            }
        }
        return (low + high) / 2;  // 返回逼近出的最终结果
    }
}
image.gif

       在这个示例中,我们使用循环和二分法来逼近二分对数。我们先设置最小范围low为0,最大范围highnumber,然后使用二分法不断缩小范围,直到找到一个足够接近的结果。

       在每次循环中,我们计算中间值mid,将以base为底、mid的指数幂保存在变量calculated中。如果calculated小于number,说明我们的中间值太小,因此我们更新lowmid,把范围缩小到midhigh之间。如果calculated大于等于number,说明我们的中间值太大,因此我们更新highmid,将范围缩小到lowmid之间。这样通过不断的二分法逼近,直到范围足够小以满足精度要求,我们得到逼近的结果。

       最后,我们返回lowhigh的平均值作为最终的逼近结果。

       请注意,这个方法只适用于正数的二分对数运算。如果需要处理负数或0,或者要处理更复杂的情况,请引入更多的条件检查和逻辑。

       

十、实现计算大数的指数模

       在计算大数的指数模时,可以使用快速幂算法(也称为幂的二进制拆分算法)。这种算法可以高效地计算大数的指数,并且可以防止溢出。

       下面是一个用 Java 编程实现快速幂算法计算大数的指数模的示例:

import java.math.BigInteger;
public class ModuloExponentiation {
    public static BigInteger modPow(BigInteger base, BigInteger exponent, BigInteger modulus) {
        BigInteger result = BigInteger.ONE;
        base = base.mod(modulus); // 对底数先取模
        while (exponent.compareTo(BigInteger.ZERO) > 0) { // 当指数大于 0 时循环
            if (exponent.and(BigInteger.ONE).compareTo(BigInteger.ONE) == 0) { // 如果指数的最低位为 1
                result = result.multiply(base).mod(modulus); // 将 base 乘到结果中并对模取余
            }
            base = base.multiply(base).mod(modulus); // base 自乘并对模取余
            exponent = exponent.shiftRight(1); // 右移一位
        }
        return result;
    }
    public static void main(String[] args) {
        BigInteger base = new BigInteger("12345678901234567890");
        BigInteger exponent = new BigInteger("98765432109876543210");
        BigInteger modulus = new BigInteger("1000000007");
        BigInteger result = modPow(base, exponent, modulus);
        System.out.println("Result: " + result);
    }
}
image.gif

       在上述示例中,我们使用了 Java 的 BigInteger 类来处理大数运算,并实现了一个高效的 modPow() 方法来计算大数的指数模。这个方法避免了直接计算指数后再取模所带来的溢出风险,而是在每一步计算中都及时取模,确保计算过程中的值始终保持在可控范围内。

       

十一、实现平方根函数

       在 Java 中,可以使用牛顿迭代法来实现一个求平方根的函数。牛顿迭代法是一种迭代的方法,它可以逐步逼近一个函数的零点,从而求得函数的解。

       下面是一个用 Java 编程实现求平方根函数的示例:

public class SqrtCalculator {
    public static double sqrt(double x) {
        if (x < 0) {
            throw new IllegalArgumentException("Input must be a non-negative number");
        }
        
        double guess = x;  // 初始猜测值为 x
        double error = 1e-15;  // 定义误差范围
        while (Math.abs(guess - x / guess) > error * guess) {
            guess = (x / guess + guess) / 2.0;  // 使用牛顿迭代法逐步逼近平方根
        }
        return guess;
    }
    public static void main(String[] args) {
        double number = 25.0;
        double result = sqrt(number);
        System.out.println("Square root of " + number + " is " + result);
    }
}
image.gif

       在上述示例中,我们定义了一个 sqrt() 方法来计算一个数的平方根,其中使用了牛顿迭代法。在 main() 方法中,我们调用 sqrt() 方法来计算 25 的平方根,并打印结果。

       需要注意的是,上述示例中的实现是简化的,实际应用中可能需要考虑更多的边界条件和错误处理。

       

十二、实现斐波那契数列的快速计算

       斐波那契数列可以通过矩阵快速幂的方法进行高效计算。这种方法可以在 O(log n) 的时间复杂度内计算斐波那契数列的第 n 项。

       以下是一个使用 Java 编程实现斐波那契数列快速计算的示例:

public class Fibonacci {
    public static long fibonacci(int n) {
        if (n < 0) {
            throw new IllegalArgumentException("Input must be a non-negative number");
        }
        
        if (n == 0) {
            return 0;
        }
        
        long[][] baseMatrix = {{1, 1}, {1, 0}};  // 基础矩阵
        powerMatrix(baseMatrix, n - 1);  // 将基础矩阵进行快速幂计算
        return baseMatrix[0][0]; // 返回结果
    }
    // 矩阵快速幂计算
    private static void powerMatrix(long[][] matrix, int n) {
        if (n <= 0) {
            return;
        }
        
        long[][] result = {{1, 0}, {0, 1}};  // 初始化为单位矩阵
        while (n > 0) {
            if ((n & 1) == 1) {  // 如果 n 的二进制表示的最低位为 1
                multiplyMatrix(result, matrix);  // 累乘当前的基础矩阵
            }
            n >>= 1;  // 右移,相当于 n 除以 2
            multiplyMatrix(matrix, matrix);  // 基础矩阵自乘
        }
        // 将最终结果更新到原始矩阵
        matrix[0][0] = result[0][0];
        matrix[0][1] = result[0][1];
        matrix[1][0] = result[1][0];
        matrix[1][1] = result[1][1];
    }
    // 矩阵乘法
    private static void multiplyMatrix(long[][] m1, long[][] m2) {
        long a = m1[0][0] * m2[0][0] + m1[0][1] * m2[1][0];
        long b = m1[0][0] * m2[0][1] + m1[0][1] * m2[1][1];
        long c = m1[1][0] * m2[0][0] + m1[1][1] * m2[1][0];
        long d = m1[1][0] * m2[0][1] + m1[1][1] * m2[1][1];
        m1[0][0] = a;
        m1[0][1] = b;
        m1[1][0] = c;
        m1[1][1] = d;
    }
    public static void main(String[] args) {
        int n = 10;
        long result = fibonacci(n);
        System.out.println("The " + n + "-th Fibonacci number is: " + result);
    }
}
image.gif

       在上述示例中,我们使用了矩阵快速幂的方法来计算斐波那契数列的第 n 项。这种方法利用了矩阵的幂运算特性,可以在较短的时间内计算出较大项的斐波那契数。

       

十三、实现整数划分问题

       整数划分问题可以使用动态规划来解决。动态规划是一种将原问题拆分成子问题来解决的技术,通常适用于具有重叠子问题和最优子结构性质的问题。

       以下是一个使用 Java 编程实现整数划分问题的示例:

public class IntegerPartition {
    public static int countPartitions(int n) {
        int[] partitionCount = new int[n + 1];
        partitionCount[0] = 1; // 初始化边界条件
        for (int i = 1; i <= n; i++) {
            for (int j = i; j <= n; j++) {
                partitionCount[j] += partitionCount[j - i];
            }
        }
        return partitionCount[n];
    }
    public static void main(String[] args) {
        int n = 5;
        int result = countPartitions(n);
        System.out.println("The number of partitions for " + n + " is: " + result);
    }
}
image.gif

       在上述示例中,我们定义了一个 countPartitions 方法来计算整数 n 的划分数量。具体来说,我们使用了一个数组 partitionCount 来记录每个整数的划分数量,然后通过迭代计算每个整数的划分数量,最终得到整数 n 的划分数量。

       在主函数中,我们调用 countPartitions 方法来计算 5 的划分数量,并输出结果。整数划分算法的关键就在于动态规划的思想,通过解决小规模问题,逐步构建出大规模问题的解。

       

十四、实现复数幂次

       复数的幂次运算可以通过将复数表示为实部和虚部的形式,并使用欧拉公式进行计算。欧拉公式表达了复数的指数函数与三角函数之间的关系。

       以下是一个使用 Java 编程实现复数幂次的示例:

public class ComplexPower {
    public static ComplexNumber power(ComplexNumber base, double exponent) {
        double realPart = Math.pow(base.getReal(), exponent) * Math.cos(exponent * base.getImaginary());
        double imaginaryPart = Math.pow(base.getReal(), exponent) * Math.sin(exponent * base.getImaginary());
        return new ComplexNumber(realPart, imaginaryPart);
    }
    public static void main(String[] args) {
        ComplexNumber base = new ComplexNumber(2.0, 3.0);
        double exponent = 2.0;
        ComplexNumber result = power(base, exponent);
        System.out.println("The result is: " + result);
    }
}
image.gif

       在上述示例中,我们定义了一个 ComplexPower 类,其中包含一个 power 方法来计算复数的幂次。我们使用欧拉公式将复数的幂次运算转化为三角函数的计算,然后根据实部和虚部的计算公式得到最终结果。

       在主函数中,我们创建了一个复数对象 base,然后调用 power 方法计算该复数的平方,最后输出结果。

       需要注意的是,上述示例中使用了一个自定义的 ComplexNumber 类来表示复数,该类包含了实部和虚部的属性以及相关的访问方法。在实际应用中,你可能需要根据自己的需求来选择使用现有的复数库或自定义实现复数类。

       

十五、实现指定范围包含的素数

       编程实现指定范围内包含的素数,可以使用以下的步骤来实现:

       1. 定义一个函数 isPrime,用来判断一个数是否为素数。素数是大于1且只能被1和自身整除的数。

public static boolean isPrime(int n) {
    if (n <= 1) {
        return false;
    }
    for (int i = 2; i <= Math.sqrt(n); i++) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}
image.gif

       2. 定义一个函数 findPrimesInRange,用来查找指定范围内的所有素数,并将它们打印出来。

public static void findPrimesInRange(int start, int end) {
    for (int i = start; i <= end; i++) {
        if (isPrime(i)) {
            System.out.print(i + " ");
        }
    }
    System.out.println();
}
image.gif

       3. 在主程序中调用 findPrimesInRange 函数并传入指定的范围参数。

public static void main(String[] args) {
    int start = 101; // 指定范围的起始值
    int end = 200; // 指定范围的终止值
    
    System.out.println("素数范围 " + start + " 到 " + end + ":");
    findPrimesInRange(start, end);
}
image.gif

       运行以上代码,将会输出在指定范围内的素数。

       

十六、实现水仙花数

       水仙花数:指一个n位数 (n≥3),它的每个位上的数字的 n 次幂之和等于它本身。例如:1^3 + 5^3 + 3^3 = 153。

       编程实现

public class NarcissisticNumber {
    public static boolean isNarcissisticNumber(int num) {
        String strNum = String.valueOf(num);
        int n = strNum.length();
        int sum = 0;
        for(int i = 0; i < n; i++) {
            int digit = Character.getNumericValue(strNum.charAt(i));
            sum += Math.pow(digit, n);
        }
        return sum == num;
    }
    public static void findNarcissisticNumbers(int start, int end) {
        System.out.println("水仙花数范围 " + start + " 到 " + end + ":");
        for(int i = start; i <= end; i++) {
            if(isNarcissisticNumber(i)) {
                System.out.print(i + " ");
            }
        }
        System.out.println();
    }
    public static void main(String[] args) {
        int startRange = 100;
        int endRange = 1000;
        findNarcissisticNumbers(startRange, endRange);
    }
}
image.gif

       在这个示例中,isNarcissisticNumber 方法用于判断一个数是否为水仙花数。findNarcissisticNumbers 方法用于找出指定范围内的所有水仙花数,并打印它们。

       运行以上代码,将输出范围内的水仙花数。可以根据需改 startRangeendRange 的值来找到不同范围内的水仙花数。

       

十七、实现分解质因数

       在Java中,可以通过编程实现分解质因数的算法。下面是一个示例的分解质因数的Java程序,以及对实现步骤的简要分析。

       编程实现

public class PrimeFactorization {
    public static void primeFactorization(int number) {
        System.out.print("质因数分解结果:" + number + " = ");
        for (int i = 2; i <= number; i++) {
            while (number % i == 0) {
                System.out.print(i);
                number = number / i;
                if (number > 1) {
                    System.out.print(" * ");
                }
            }
        }
    }
    public static void main(String[] args) {
        int number = 60; // 要分解质因数的数字
        primeFactorization(number); // 调用分解质因数的方法
    }
}
image.gif

实现步骤分析:

  1. 创建一个Java类,并定义一个静态方法primeFactorization,该方法接受一个整数作为参数,用于进行质因数的分解。
  2. primeFactorization方法中,通过循环从2开始逐个尝试作为质因数。如果当前数能够被整除,就将这个质因数输出,并将被除数改为原来的数除以这个质因数。
  3. 如果被除数大于1,表示仍有剩余的质因数需要求解,就输出乘号然后继续寻找下一个质因数。
  4. main方法中,调用primeFactorization方法,并传入要分解的数字。

这个算法的时间复杂度为 O(logn),其中n是输入数字。因为算法在循环中不断地将n除以小于n的因数,直到n变为1为止。因此,该算法是一个高效的质因数分解方法。

       

十八、实现最大公约数和最小公倍数

       最大公约数(Greatest Common Divisor,简称GCD):指两个或多个整数中能够整除它们的最大正整数。换句话说,最大公约数是一组整数的公有因子中最大的一个。

最大公约数常用于数学、计算机科学和工程等领域,可以用来简化分数、求解方程、求解最简整数倍等问题。

       最常见的计算最大公约数的方法是使用欧几里得算法(Euclidean Algorithm)。欧几里得算法基于以下原理:两个整数a和b的最大公约数等于a被b整除的余数r,而b和r的最大公约数等于r被b整除的余数,依次类推,直到余数为0时,最大公约数就是上一个非零的余数。

       以下是一个使用欧几里得算法计算最大公约数的示例代码:

public class GCD {
    public static void main(String[] args) {
        int a = 48;
        int b = 36;
        // 计算最大公约数
        int gcd = calculateGCD(a, b);
        // 输出结果
        System.out.println("最大公约数:" + gcd);
    }
    // 使用欧几里得算法计算最大公约数
    public static int calculateGCD(int a, int b) {
        while (b != 0) {
            int remainder = a % b;
            a = b;
            b = remainder;
        }
        return a;
    }
}
image.gif

       在这个示例中,我们使用欧几里得算法计算整数a和b的最大公约数。我们通过迭代的方式,重复计算a除以b的余数,并将b赋值给a,将余数赋值给b,直到余数为0。最后,最大公约数就是上一个非零的余数。

       在示例中,我们计算了48和36的最大公约数,结果为12。

       需要注意的是,欧几里得算法对于计算最大公约数非常高效,时间复杂度为O(log n),其中n是a和b中较大的整数。因此,它是一种常用且有效的方法来计算最大公约数。

       

       最小公倍数(Least Common Multiple,简称LCM):指两个或多个整数的公倍数中最小的一个整数。换句话说,最小公倍数是能够被给定整数整除的最小正整数。

       计算最小公倍数常常用于化简分数、求解最简整数倍等问题。

       常见的计算最小公倍数的方法是通过最大公约数(Greatest Common Divisor,简称GCD)来求解。两个整数a和b的最小公倍数等于它们的乘积除以最大公约数。这是因为两个整数的乘积除以最大公约数等于两个整数的公倍数中的最小值。

       以下是一个示例代码,演示如何计算两个整数的最小公倍数:

public class LCM {
    public static void main(String[] args) {
        int a = 12;
        int b = 18;
        // 计算最小公倍数
        int lcm = calculateLCM(a, b);
        // 输出结果
        System.out.println("最小公倍数:" + lcm);
    }
    // 计算最小公倍数
    public static int calculateLCM(int a, int b) {
        int gcd = calculateGCD(a, b);
        int lcm = (a * b) / gcd;
        return lcm;
    }
    // 使用欧几里得算法计算最大公约数
    public static int calculateGCD(int a, int b) {
        while (b != 0) {
            int remainder = a % b;
            a = b;
            b = remainder;
        }
        return a;
    }
}
image.gif

       在这个示例中,我们先使用欧几里得算法(GCD)计算出12和18的最大公约数,结果为6。然后,我们将12和18的乘积除以最大公约数,得到最小公倍数为36。

       注意,最小公倍数可以通过最大公约数计算得到,因此在计算最小公倍数之前,需要先计算最大公约数。

相关文章
|
7天前
|
JSON Java Apache
非常实用的Http应用框架,杜绝Java Http 接口对接繁琐编程
UniHttp 是一个声明式的 HTTP 接口对接框架,帮助开发者快速对接第三方 HTTP 接口。通过 @HttpApi 注解定义接口,使用 @GetHttpInterface 和 @PostHttpInterface 等注解配置请求方法和参数。支持自定义代理逻辑、全局请求参数、错误处理和连接池配置,提高代码的内聚性和可读性。
|
9天前
|
安全 Java 编译器
JDK 10中的局部变量类型推断:Java编程的简化与革新
JDK 10引入的局部变量类型推断通过`var`关键字简化了代码编写,提高了可读性。编译器根据初始化表达式自动推断变量类型,减少了冗长的类型声明。虽然带来了诸多优点,但也有一些限制,如只能用于局部变量声明,并需立即初始化。这一特性使Java更接近动态类型语言,增强了灵活性和易用性。
91 53
|
8天前
|
存储 安全 Java
Java多线程编程的艺术:从基础到实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及其实现方式,旨在帮助开发者理解并掌握多线程编程的基本技能。文章首先概述了多线程的重要性和常见挑战,随后详细介绍了Java中创建和管理线程的两种主要方式:继承Thread类与实现Runnable接口。通过实例代码,本文展示了如何正确启动、运行及同步线程,以及如何处理线程间的通信与协作问题。最后,文章总结了多线程编程的最佳实践,为读者在实际项目中应用多线程技术提供了宝贵的参考。 ####
|
5天前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
7天前
|
存储 缓存 安全
在 Java 编程中,创建临时文件用于存储临时数据或进行临时操作非常常见
在 Java 编程中,创建临时文件用于存储临时数据或进行临时操作非常常见。本文介绍了使用 `File.createTempFile` 方法和自定义创建临时文件的两种方式,详细探讨了它们的使用场景和注意事项,包括数据缓存、文件上传下载和日志记录等。强调了清理临时文件、确保文件名唯一性和合理设置文件权限的重要性。
20 2
|
8天前
|
Java UED
Java中的多线程编程基础与实践
【10月更文挑战第35天】在Java的世界中,多线程是提升应用性能和响应性的利器。本文将深入浅出地介绍如何在Java中创建和管理线程,以及如何利用同步机制确保数据一致性。我们将从简单的“Hello, World!”线程示例出发,逐步探索线程池的高效使用,并讨论常见的多线程问题。无论你是Java新手还是希望深化理解,这篇文章都将为你打开多线程的大门。
|
9天前
|
安全 Java 编译器
Java多线程编程的陷阱与最佳实践####
【10月更文挑战第29天】 本文深入探讨了Java多线程编程中的常见陷阱,如竞态条件、死锁、内存一致性错误等,并通过实例分析揭示了这些陷阱的成因。同时,文章也分享了一系列最佳实践,包括使用volatile关键字、原子类、线程安全集合以及并发框架(如java.util.concurrent包下的工具类),帮助开发者有效避免多线程编程中的问题,提升应用的稳定性和性能。 ####
36 1
|
6月前
|
存储 算法 Java
【数据结构与算法】1、学习动态数组数据结构(基本模拟实现 Java 的 ArrayList 实现增删改查)
【数据结构与算法】1、学习动态数组数据结构(基本模拟实现 Java 的 ArrayList 实现增删改查)
170 0
|
存储 算法 Java
数据结构算法学习打卡week2 (Java)
数据结构算法学习打卡week2 (Java)
73 0
|
Rust 算法 安全
【算法学习】1588. 所有奇数长度子数组的和(java / c / c++ / python / go / rust)
给你一个正整数数组 arr ,请你计算所有可能的奇数长度子数组的和。 子数组 定义为原数组中的一个连续子序列。 请你返回 arr 中 所有奇数长度子数组的和 。
【算法学习】1588. 所有奇数长度子数组的和(java / c / c++ / python / go / rust)