꒰˃͈꒵˂͈꒱ write in front꒰˃͈꒵˂͈꒱
ʕ̯•͡˔•̯᷅ʔ大家好,我是xiaoxie.希望你看完之后,有不足之处请多多谅解,让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ ა
本文由xiaoxieʕ̯•͡˔•̯᷅ʔ原创 CSDN如需转载还请通知˶⍤⃝˶
个人主页:xiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客
系列专栏:xiaoxie的牛客网刷题系列专栏——CSDN博客●’ᴗ’σσணღ*
我的目标:”团团等我( ◡̀_◡́ ҂)”

感谢您的阅读!

(⸝⸝⸝›ᴥ‹⸝⸝⸝ )欢迎各位→点赞 + 收藏⭐️ + 留言​+关注(互三必回)!

今天在牛客网刷题时,碰到了两题,虽然很简单,但是往深处想,又有不一样的见解,所以博主就把感想写下来分享给大家

首先请先看题

我想很多人和我一样一开始觉得这题不是很简单嘛它的第n项的表达式都给出来了,解决这个问题不是轻松拿捏嘛直接

import java.util.Scanner; // 注意类名必须为 Main, 不要有任何 package xxx 信息public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextInt()) { // 注意 while 处理多个 caseint n = in.nextInt();double a =0;double b = 0;for(int i=1;i<=n;i++){b=b+Math.pow(-1,i-1)*(2*i-1);a=a+1.0/b;}System.out.printf("%.3f",a);}}}

这样是可以算出答案的,但博主突然灵机一动,把分母的值算出来看一下就发现原来算出来之后,是有规律的啊

它的分母计算出来之后是 1 + -2 +3 -4 +5 -6+……既然知道了分母是这样的规律那我们就可以稍微的简化一下代码

import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int n = in.nextInt();double sum = 0.0;int flag = 1;for (int i = 1; i <= n; i++) { sum +=flag*(1.0/i); flag = -flag; }System.out.printf("%.3f", sum);}}

虽然说两个方法不见得谁比谁好,特别是我修改后的代码也算是属于投机取巧,但博主想说的是,抛开这个问题不讲,在我们平时做题的时候多角度的看待问题,我觉得值得提倡

还有一题也是非常简单的一题

也是一样一开始博主是这样写的使用两个for循环来解

import java.util.*; public class Main{public static void main(String[] args){Scanner sc=new Scanner(System.in);int x=sc.nextInt();int count=0;for(int i=1;i<=x;i++){int sum=0;for(int j=1;j<=i;j++){sum+=j;}count+=sum;}System.out.println(count); 

写完后博主突然发现这题不是可以用初高中的数学知识用求前n项和来解这题嘛于是博主修改一下代码,使用公式S=n*(n+1)/2 来解

import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int n = in.nextInt();int sum = 0;for (int i = 1; i <= n; i++) {sum += (i * (i + 1)) / 2;}System.out.println(sum);}}

其实这题一样也是说不上修改就比没修改的代码性能好到那里去,但是博主觉得在我们平常编译代码的时候,用一用数学的公式可以替我们简化一些代码,并且能够在解题时拓展我们的思维

让我们更好地理解数学公式优化代码。所以,下面来看一下这道题的解法。

首先,我们来看一下题目要求的函数:

public boolean canJump(int[] nums) { // TODO: Implement the logic here return false; // Placeholder return statement }

题目要求我们实现一个函数,判断一个数组 nums 中的元素能否跳跃到最后一个位置。而我们需要通过修改代码来使得函数的执行效率尽可能高。

接下来,我们来分析一下题目的思路。对于这道题,我们可以采用贪心算法的思路来解决。我们遍历数组中的每个位置,并实时维护能够跳跃到的最远位置。对于当前遍历到的位置,如果它在能够跳跃到的最远位置的范围内,那么我们就更新能够跳跃到的最远位置,否则,我们就判断当前位置是否能够跳跃到最远位置,如果不能,就直接返回 False。最后,如果我们遍历完了整个数组,且能够跳跃到最远位置,那么就返回 True。

具体思路可以用以下代码来实现:

public boolean canJump(int[] nums) {int n = nums.length;int maxPos = nums[0]; // 可以到达的最远位置for (int i = 1; i = i) { // 如果当前位置可以到达maxPos = Math.max(maxPos, i + nums[i]); // 更新最远能到达的位置if (maxPos >= n - 1) { // 如果已经到达数组末尾return true;}} else {return false; // 如果当前位置不能到达,直接返回 false}}return false; // 遍历完整个数组都没有到达数组末尾,直接返回 false}

这段代码的时间复杂度为 O(n),因为我们只需要遍历一次整个数组就能得到结果。但是,我们可以通过一些数学公式来简化代码,使得时间复杂度更低。

我们观察一下上面的代码:

 maxPos = Math.max(maxPos, i + nums[i]);

我们在更新 max_pos 时,计算的是当前位置可以到达的最远位置 i + nums[i] 和已经可以到达的最远位置 max_pos 中的较大值。这里,我们可以使用一个变量来维护可以到达的最远位置,并且不用每次都调用 max 函数来更新它。

具体操作是,我们令一个整数变量 end 记录当前能够到达的最远位置,而变量 max_pos 则记录已经遍历过的位置中能够到达的最远位置。当我们遍历到位置 i 时,如果 i > end,那么说明当前位置无法到达,直接返回 False。否则,我们更新 end 的值为 max(end, i + nums[i]),然后判断更新后的 end 是否已经达到数组的末尾,如果是,就返回 True。

具体实现如下:

public boolean canJump(int[] nums) {int n = nums.length;int end = 0; // 当前能够到达的最远位置for (int i = 0; i  end) { // 当前位置无法到达return false;}end = Math.max(end, i + nums[i]); // 更新能够到达的最远位置if (end >= n - 1) { // 如果已经到达末尾位置return true;}}return true;}

这段代码的时间复杂度为 O(n),但是和上面的代码相比,更加简洁。这就是利用数学公式优化代码的方法。

谢谢大家的阅读!