招聘笔试JAVA题,春招秋招软件开发工程师笔试专题。
1.合并两个有序数组
给你两个按非递减顺序排列的整数数组nums1和nums2,另有两个整数m和n,分别表示nums1和nums2中的元素数目。
请你合并nums2到nums1中,使合并后的数组同样按非递减顺序排列。
**注意:**最终,合并后数组不应由函数返回,而是存储在数组nums1中。为了应对这种情况,nums1的初始长度为m + n,其中前m个元素表示应合并的元素,后n个元素为0,应忽略。nums2的长度为n。
示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3 输出:[1,2,2,3,5,6] 解释:需要合并 [1,2,3] 和 [2,5,6] 。 合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。示例 2:
输入:nums1 = [1], m = 1, nums2 = [], n = 0 输出:[1] 解释:需要合并 [1] 和 [] 。 合并结果是 [1] 。示例 3:
输入:nums1 = [0], m = 0, nums2 = [1], n = 1 输出:[1] 解释:需要合并的数组是 [] 和 [1] 。 合并结果是 [1] 。 注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。提示:
nums1.length == m + nnums2.length == n0 <= m, n <= 2001 <= m + n <= 200-109 <= nums1[i], nums2[j] <= 109
**进阶:**你可以设计实现一个时间复杂度为O(m + n)的算法解决此问题吗?
//正常方法// import java.util.*;// class Solution {// public void merge(int[] nums1, int m, int[] nums2, int n) {// for(int i=m;i<nums1.length;i++)// nums1[i]=nums2[i-m];// Arrays.sort(nums1);// // for(int i=0;i<nums1.length;i++)// // System.out.println(nums1[i]);// }// }// 进阶classSolution{publicvoidmerge(int[]nums1,intm,int[]nums2,intn){// 定义三个指针,分别指向 nums1 有效元素末尾、nums2 末尾、nums1 实际末尾inti=m-1;intj=n-1;intk=m+n-1;// 从后往前合并,避免覆盖 nums1 中未处理的元素while(i>=0&&j>=0){// 将较大的元素放到 nums1 后面if(nums1[i]>nums2[j]){nums1[k--]=nums1[i--];}else{nums1[k--]=nums2[j--];}}// 如果 nums2 还有剩余元素,直接复制到 nums1 前面while(j>=0){nums1[k--]=nums2[j--];}}}2.移除元素
给你一个数组nums和一个值val,你需要原地移除所有数值等于val的元素。元素的顺序可能发生改变。然后返回nums中与val不同的元素的数量。
假设nums中不等于val的元素数量为k,要通过此题,您需要执行以下操作:
- 更改
nums数组,使nums的前k个元素包含不等于val的元素。nums的其余元素和nums的大小并不重要。 - 返回
k。
用户评测:
评测机将使用以下代码测试您的解决方案:
int[] nums = [...]; // 输入数组 int val = ...; // 要移除的值 int[] expectedNums = [...]; // 长度正确的预期答案。 // 它以不等于 val 的值排序。 int k = removeElement(nums, val); // 调用你的实现 assert k == expectedNums.length; sort(nums, 0, k); // 排序 nums 的前 k 个元素 for (int i = 0; i < actualLength; i++) { assert nums[i] == expectedNums[i]; }如果所有的断言都通过,你的解决方案将会通过。
示例 1:
输入:nums = [3,2,2,3], val = 3 输出:2, nums = [2,2,_,_] 解释:你的函数函数应该返回 k = 2, 并且 nums 中的前两个元素均为 2。 你在返回的 k 个元素之外留下了什么并不重要(因此它们并不计入评测)。示例 2:
输入:nums = [0,1,2,2,3,0,4,2], val = 2 输出:5, nums = [0,1,4,0,3,_,_,_] 解释:你的函数应该返回 k = 5,并且 nums 中的前五个元素为 0,0,1,3,4。 注意这五个元素可以任意顺序返回。 你在返回的 k 个元素之外留下了什么并不重要(因此它们并不计入评测)。提示:
0 <= nums.length <= 1000 <= nums[i] <= 500 <= val <= 100
classSolution{publicintremoveElement(int[]nums,intval){// int sum = 0;// // int flag=0;// // int[] arr = new int[nums.length];// for (int i = 0; i < nums.length; i++) {// // for (int j = 0; j < nums.length; j++) {// // if (nums[i] == val) {// // // sum++;// // nums[i] = 101;// // } else {// if (nums[i] != val) {// // sum++;// nums[sum++] = nums[i];// // arr[i] = nums[i];// // return nums[i];// // return nums[i];// }// // }// }// System.out.println(sum);// for(int i=0 ; i<nums.length ; i++)// {// // if(arr[i] != 101) nums[flag++] = arr[i];// if(nums[i] != 101) nums[flag++] = nums[i];// // System.out.println("__");// // System.out.println(nums[i]);// }inti=0;for(;i<nums.length;i++){if(nums[i]==val){// 找到第一个需要替换的位置break;}}// 从找到的位置开始,用后面的非val元素替换for(intj=i;j<nums.length;j++){if(nums[j]!=val){nums[i++]=nums[j];}}returni;// return sum;}}3.删除有序数组中的重复项
给你一个非严格递增排列的数组nums,请你** 原地** 删除重复出现的元素,使每个元素只出现一次,返回删除后数组的新长度。元素的相对顺序应该保持一致。然后返回nums中唯一元素的个数。
考虑nums的唯一元素的数量为k,你需要做以下事情确保你的题解可以被通过:
- 更改数组
nums,使nums的前k个元素包含唯一元素,并按照它们最初在nums中出现的顺序排列。nums的其余元素与nums的大小不重要。 - 返回
k。
判题标准:
系统会用下面的代码来测试你的题解:
int[] nums = [...]; // 输入数组 int[] expectedNums = [...]; // 长度正确的期望答案 int k = removeDuplicates(nums); // 调用 assert k == expectedNums.length; for (int i = 0; i < k; i++) { assert nums[i] == expectedNums[i]; }如果所有断言都通过,那么您的题解将被通过。
示例 1:
输入:nums = [1,1,2] 输出:2, nums = [1,2,_] 解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。示例 2:
输入:nums = [0,0,1,1,1,2,2,3,3,4] 输出:5, nums = [0,1,2,3,4] 解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。提示:
1 <= nums.length <= 3 * 104-104 <= nums[i] <= 104nums已按非严格递增排列
classSolution{publicintremoveDuplicates(int[]nums){// 给你一个 非严格递增排列 的数组 nums//请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。intk=1;// int[] arr = new int[nums.length];// for (int i = 0; i < nums.length; i++) {// // 第一个// if (i == 0)// arr[k++] = nums[i];// // 其他情况遍历// for (int j = 0; j < k; j++) {// if (nums[i] == arr[j]) {// break;// }// if(j == k-1){// arr[k++] = nums[i];// }// }// }// int y=0;// for (int j = 0; j < k; j++) nums[y++] = arr[j];// return k;for(inti=1;i<nums.length;i++){if(nums[k-1]==nums[i]){continue;}nums[k++]=nums[i];}// System.out.println(k);// 更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。returnk;}}4.删除有序数组中的重复项 II
给你一个有序数组nums,请你** 原地** 删除重复出现的元素,使得出现次数超过两次的元素只出现两次,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在原地 修改输入数组并在使用 O(1) 额外空间的条件下完成。
说明:
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以**「引用」**方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
你可以想象内部操作如下:
// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝 int len = removeDuplicates(nums); // 在函数里修改输入数组对于调用者是可见的。 // 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。 for (int i = 0; i < len; i++) { print(nums[i]); }示例 1:
输入:nums = [1,1,1,2,2,3] 输出:5, nums = [1,1,2,2,3] 解释:函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3。 不需要考虑数组中超出新长度后面的元素。示例 2:
输入:nums = [0,0,1,1,1,1,2,3,3] 输出:7, nums = [0,0,1,1,2,3,3] 解释:函数应返回新长度 length = 7, 并且原数组的前七个元素被修改为 0, 0, 1, 1, 2, 3, 3。不需要考虑数组中超出新长度后面的元素。提示:
1 <= nums.length <= 3 * 104-104 <= nums[i] <= 104nums已按升序排列
classSolution{publicintremoveDuplicates(int[]nums){// 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。// int k=1;// int count=0;// for(int i=1 ; i<nums.length ;i++){// if(nums[k-1] == nums[i]){// count++;// if(count == 1){// nums[k++] = nums[i];// }// if(count >= 2){// continue;// }// }else{// nums[k++] = nums[i];// count = 0;// }// }// // System.out.println(k);// return k;// 数组长度小于3时,直接返回原长度if(nums.length<=2){returnnums.length;}// 慢指针,指向当前需要填充的位置intk=2;// 快指针,遍历整个数组for(inti=2;i<nums.length;i++){// 如果当前元素与k-2位置的元素不同,说明可以保留if(nums[i]!=nums[k-2]){nums[k++]=nums[i];}}returnk;// 不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。}}5.药水合成
importjava.util.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息publicclassMain{// 存储各级药材的数量,索引0对应等级1,索引1对应等级2,以此类推staticint[]pros=newint[10];publicstaticvoidmain(String[]args){Scannerin=newScanner(System.in);// 输入材料数量和订单数量intproSum=in.nextInt();intorderSum=in.nextInt();// 读取仓库中的药材等级for(inti=0;i<proSum;i++){intlevel=in.nextInt();pros[level-1]++;// 等级1存放在索引0}// 读取订单所需的药材等级int[]orders=newint[orderSum];for(inti=0;i<orderSum;i++){orders[i]=in.nextInt();}// 计算最多能满足多少订单intsatisfiedOrders=0;for(intorder:orders){if(canFulfill(order)){satisfiedOrders++;}}System.out.println("最多能满足 "+satisfiedOrders+" 个订单");}// 检查是否能满足一个订单,若能则消耗相应药材privatestaticbooleancanFulfill(inttargetLevel){// 如果目标等级超过10,无法满足if(targetLevel>10){returnfalse;}// 检查当前等级是否有足够药材if(pros[targetLevel-1]>0){pros[targetLevel-1]--;returntrue;}// 如果当前等级没有足够药材,尝试用低一级的药材合成if(targetLevel>1){// 需要2个低一级的药材才能合成1个当前等级的药材if(canFulfill(targetLevel-1)&&canFulfill(targetLevel-1)){returntrue;}}// 无法满足returnfalse;}}