第一题:大数减法
输入描述:输入两个数字
输出描述:两个输入数字的差
输入示例:
1 2
输出示例:
-1
这题有点细节要注意:
1、大数减法肯定说明输入的数据是超过int类型的大数据,肯定就不能直接用 字符串转int了
2、在java中可以直接导入大数库,import java.math.BigInteger;
3、补充字符串转 整数的api
- 如果是转为int型整数
int number1 = Integer.parseInt(string1); // 将输入的字符串转换为整数System.out.println(num.toString()); //将插值转换为 字符串 并返回
- 如果是转为BigInter型整数(大数)
BigInteger number1 = new BigInteger(s1);//将输入的字符串转化为大整数BigInteger类型
BigInteger difference = number1.subtract(number2); //计算大数的差值也不一样
System.out.println(difference.toString()); //将插值转换为 字符串 并返回
import java.util.*;
import java.math.BigInteger;
public class Main{
public static void main (String[] args) {
Scanner sc = new Scanner(System.in);
//输入两个数字(字符串形式)
String s1 = sc.next();
String s2 = sc.next();
//将输入的字符串转化为大整数BigInteger类型
BigInteger number1 = new BigInteger(s1);
BigInteger number2 = new BigInteger(s2);
//计算差值
//BigInteger difference = number1 - number2;
BigInteger difference = number1.subtract(number2);
//将插值转换为 字符串 并返回
System.out.println(difference.toString());
}
}
第二题:滑动窗口最大值(综合性非常高,复杂)
这题最坑的点在于输入格式的 处理:
这题的输入就是一个长字符串,就是nums = [1,3,-1,-3,5,3,6,7], k = 3,需要自己提取出来数组nums和滑动窗口 k!!!较为复杂,需要很熟悉输入操作。
① 按 ", k = " 分割输入字符串,得到两个部分:
nums
部分和k
值部分。String[] parts = input.split(", k = ");
②提取 nums 部分,去掉方括号,得到逗号分隔的数字字符串("1,3,-1,-3,5,3,6,7")
String numsPart = parts[0].substring(parts[0].indexOf('[') + 1, parts[0].indexOf(']'));③提取 k 值部分,并将其转换为整数(总结一下,
parts[1].trim()
的目的是确保提取的k
值字符串没有首尾空白字符,以便正确地将其转换为整数。)(" 3 ")
int k = Integer.parseInt(parts[1].trim());④将 nums 部分按逗号分割成字符串数组(["1", "3", "-1", "-3", "5", "3", "6", "7"])
String[] numsStringArray = numsPart.split(",");⑤初始化整数数组 nums(大小为numsStringArray.length)
int[] nums = new int[numsStringArray.length];⑥将字符串数组中的每个元素转换为整数,并存储到 nums 数组中
for (int i = 0; i < numsStringArray.length; i++) {
nums[i] = Integer.parseInt(numsStringArray[i].trim());
}
至此就将该长字符串的nums[]数组 和 k值提取出来了,接下来再计算!
②的补充说明,用到了 字符串String 的哪些方法:
indexOf(char ch)
:
- 该方法返回指定字符在字符串中第一次出现的索引。
parts[0].indexOf('[')
:返回字符'['
在parts[0]
中第一次出现的位置。parts[0].indexOf(']')
:返回字符']'
在parts[0]
中第一次出现的位置。
substring(int beginIndex, int endIndex)
: [ 左闭 右开)
- 该方法返回一个新字符串,它是此字符串的一个子字符串。
parts[0].substring(beginIndex, endIndex)
:返回从beginIndex
开始到endIndex
结束的子字符串。parts[0].substring(parts[0].indexOf('[') + 1, parts[0].indexOf(']'))
:返回从字符'['
之后(索引加1)的字符开始,到字符']'
之前的子字符串。通过这些方法,我们能够准确提取出方括号
[]
之间的内容,即nums
数组的字符串部分。这个子字符串之后会被进一步解析成整数数组。
import java.util.*;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Scanner;
public class Main{
public static void main (String[] args) {
Scanner sc = new Scanner(System.in);
//输入数组 和 滑动窗口值大小 k
// 读取 nums 列表 (有技巧 ,就是 读取方式是 用逗号隔开)
//System.out.print("请输入 nums 列表,以逗号分隔 (例如 1,3,-1,-3,5,3,6,7): ");
String input = sc.nextLine();
// 提取 nums 和 k 值
// 按照 ", k = " 分割输入字符串,得到两个部分:nums 部分和 k 值部分
String[] parts = input.split(", k = ");
// 提取 nums 部分,去掉方括号,得到逗号分隔的数字字符串
String numsPart = parts[0].substring(parts[0].indexOf('[') + 1, parts[0].indexOf(']'));
// 提取 k 值部分,并将其转换为整数
int k = Integer.parseInt(parts[1].trim());
// 将 nums 部分按逗号分割成字符串数组
String[] numsStringArray = numsPart.split(",");
// 初始化整数数组 nums
int[] nums = new int[numsStringArray.length];
// 将字符串数组中的每个元素转换为整数,并存储到 nums 数组中
for (int i = 0; i < numsStringArray.length; i++) {
nums[i] = Integer.parseInt(numsStringArray[i].trim());
}
//计算滑动窗口最大值与最小值的差的最大值
int res = maxDiffInSlidingWindow(nums,k);
//输出结果
System.out.println(res);
}
public static int maxDiffInSlidingWindow(int[] nums, int k) {
if (nums == null || nums.length == 0 || k <= 0) {
return 0;
}
int n = nums.length;
int maxDiff = Integer.MIN_VALUE;
//定义两个双端队列,分别记录 滑动窗口内最大 和 最小元素索引的双端队列 maxDeque/minDeque
Deque<Integer> maxDeque = new ArrayDeque<>();
Deque<Integer> minDeque = new ArrayDeque<>();
for (int i = 0; i < n; i++) {
// 移除滑动窗口外的元素
if (!maxDeque.isEmpty() && maxDeque.peekFirst() < i - k + 1) {
maxDeque.pollFirst();
}
if (!minDeque.isEmpty() && minDeque.peekFirst() < i - k + 1) {
minDeque.pollFirst();
}
// 从maxDeque中移除所有小于当前元素的元素
while (!maxDeque.isEmpty() && nums[maxDeque.peekLast()] <= nums[i]) {
maxDeque.pollLast();
}
// 从minDeque中移除所有大于当前元素的元素
while (!minDeque.isEmpty() && nums[minDeque.peekLast()] >= nums[i]) {
minDeque.pollLast();
}
// 将当前元素添加到双端队列中
maxDeque.offerLast(i);
minDeque.offerLast(i);
// 计算滑动窗口的最大值与最小值的差,再不断更新 取得 最大值
if (i >= k - 1) {
int maxInWindow = nums[maxDeque.peekFirst()];
int minInWindow = nums[minDeque.peekFirst()];
int diff = maxInWindow - minInWindow;
maxDiff = Math.max(maxDiff, diff);
}
}
return maxDiff;
}
}
if ( !maxDeque.isEmpty() && maxDeque.peekFirst() < i - k + 1) {
maxDeque.pollFirst(); }
这段代码段用于维护一个存储当前滑动窗口内最大元素索引的双端队列
maxDeque
。它的作用是在滑动窗口移动时,如果队列的第一个元素已经不在当前窗口范围内,就将其从队列中移除。
让我们逐行解释这段代码:
!maxDeque.isEmpty() && maxDeque.peekFirst() < i - k + 1
:
!maxDeque.isEmpty()
:检查队列是否为空,确保队列中有元素可以被操作。maxDeque.peekFirst() < i - k + 1
:检查队列中的第一个元素是否不在当前窗口的范围内。这里i - k + 1
是当前窗口的左边界,如果队列中的第一个元素比左边界小,则说明该元素已经不在当前窗口内了。
maxDeque.pollFirst()
:
- 如果条件满足,即队列不为空且队列中的第一个元素已经不在当前窗口范围内,那么就从队列的头部移除该元素。
这段代码的作用是确保队列中存储的索引都在当前窗口的范围内,即只保留当前窗口内的最大元素的索引。
while (!maxDeque.isEmpty() && nums[maxDeque.peekLast()] <= nums[i]) { maxDeque.pollLast(); }
这段代码用于维护一个存储当前滑动窗口内最大元素索引的双端队列
maxDeque
。它的作用是在向队列中添加新元素时,如果发现新元素比队列尾部的元素大,则将队列尾部的元素逐个移除,直到队列为空或者队列尾部的元素大于等于新元素。
让我们逐行解释这段代码:
!maxDeque.isEmpty() && nums[maxDeque.peekLast()] <= nums[i]
:
!maxDeque.isEmpty()
:检查队列是否为空,确保队列中有元素可以被操作。nums[maxDeque.peekLast()] <= nums[i]
:比较队列中最后一个元素对应的nums
数组中的元素值与当前遍历到的元素nums[i]
的大小关系。如果队列中最后一个元素对应的值小于等于当前元素的值,则需要将队列尾部的元素逐个移除。
maxDeque.pollLast()
:
- 如果条件满足,即队列不为空且队列中最后一个元素对应的值小于等于当前元素的值,那么就从队列的尾部移除该元素。
这段代码的作用是确保队列中存储的索引对应的元素值是递减的,也就是队列中的元素按照值的大小从大到小排列。这样,在队列中的第一个元素对应的值就是当前滑动窗口内的最大值。
最后一个if判断,这段代码用于计算当前滑动窗口内的最大值和最小值,并计算它们之间的差值,然后更新最大差值
maxDiff
。
if (i >= k - 1)
:
- 这个条件判断确保当前窗口已经满足了大小为
k
。- 当遍历到第
k - 1
个元素时,即表示窗口大小已经达到k
。
int maxInWindow = nums[maxDeque.peekFirst()];
和int minInWindow = nums[minDeque.peekFirst()];
:
- 这两行代码分别从存储当前滑动窗口最大值索引的双端队列
maxDeque
和存储当前滑动窗口最小值索引的双端队列minDeque
中取出队列头部的元素,即当前滑动窗口内的最大值和最小值的索引。- 通过这两个索引,可以从原始数组
nums
中获取当前滑动窗口内的最大值和最小值。
int diff = maxInWindow - minInWindow;
:
- 这行代码计算当前滑动窗口内的最大值和最小值之间的差值。
maxDiff = Math.max(maxDiff, diff);
:
- 这行代码使用
Math.max
方法来更新最大差值maxDiff
,保留当前最大的差值。通过这些步骤,我们可以计算出每个滑动窗口内的最大值和最小值之间的差值,并找到所有差值中的最大值
maxDiff
。
第三题:软件构建
某个大型软件项目的构建系统拥有 N 个文件,文件编号从 0 到 N - 1,在这些文件中,某些文件依赖于其他文件的内容,这意味着如果文件 A 依赖于文件 B,则必须在处理文件 A 之前处理文件 B (0 <= A, B <= N - 1)。请编写一个算法,用于确定文件处理的顺序。