软件测试工程师面试刷题:简单JAVA算法题以及解法
- 移除元素
给你一个数组 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 个元素之外留下了什么并不重要(因此它们并不计入评测)。
1 class Solution { 2 public int removeElement(int[] nums, int val) { 3 if(nums.length==0){ 4 return 0; 5 } 6 int slow=0; 7 int fast=0; 8 while(fast<nums.length){ 9 if(nums[fast]==val){ 10 fast++; 11 } 12 else{ 13 nums[slow]=nums[fast]; 14 slow++; 15 fast++; 16 } 17 } 18 return slow; 19 } 20 }
- 删除有序数组中的重复项
给你一个 非严格递增排列 的数组 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
。
不需要考虑数组中超出新长度后面的元素。
1 class Solution { 2 public int removeDuplicates(int[] nums) { 3 int n=nums.length; 4 if(n==0){ 5 return 0; 6 } 7 if(n==1){ 8 return 1; 9 } 10 11 //定义两个指针,快指针表示遍历数组到达的下标位置,慢指针表示下一个不同元素要填入的位置 12 int fast=1; 13 int slow=1; 14 while(fast<n){ 15 if(nums[fast]!=nums[fast-1]){ 16 nums[slow]=nums[fast]; 17 slow++; 18 } 19 fast++; 20 } 21 return slow; 22 } 23 }
- 合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例 1:
输入:l1 = [1,2,4], l2 = [1,3,4] 输出:[1,1,2,3,4,4]
1 /** 2 * Definition for singly-linked list. 3 * public class ListNode { 4 * int val; 5 * ListNode next; 6 * ListNode() {} 7 * ListNode(int val) { this.val = val; } 8 * ListNode(int val, ListNode next) { this.val = val; this.next = next; } 9 * } 10 */ 11 class Solution { 12 public ListNode mergeTwoLists(ListNode list1, ListNode list2) { 13 //引入伪头结点:由于初始状态合并链表中无节点,因此循环第一轮时无法将节点添加到合并链表中。初始化一个辅助节点dum作为合并链表的伪头节点,将各节点添加至dum之后 14 ListNode dum=new ListNode(0); 15 ListNode cur=dum; 16 17 while(list1 !=null && list2!=null){ 18 if(list1.val<list2.val){ 19 cur.next=list1; 20 list1=list1.next; 21 } 22 else { 23 cur.next=list2; 24 list2=list2.next; 25 } 26 cur=cur.next; 27 } 28 cur.next=list1 !=null? list1:list2; 29 //合并链表在伪头结点dum之后,因此返回dum.next即可 30 return dum.next; 31 } 32 }
- 找不同
给定两个字符串 s
和 t
,它们只包含小写字母。
字符串 t
由字符串 s
随机重排,然后在随机位置添加一个字母。
请找出在 t
中被添加的字母。
示例 1:
输入:s = "abcd", t = "abcde" 输出:"e" 解释:'e' 是那个被添加的字母。
1 class Solution {
2 public char findTheDifference(String s, String t) {
3 if(s==null) {
4 return t.charAt(0);
5 }
6
7 int[] count = new int[26];
8 for(char c:s.toCharArray()){
9 //char c是当前字符
10 //'a'是字符常量,在ASCII中值为97
11 // c-'a'计算的是字符c相对于'a'的偏移量
12 //如果c='a', 'a'-'a'=0
13 //如果c='b', 'b'-'a'=1
14 //所以count[0]对应字母a, count[1]对应字母b...
15 count[c-'a']++;
16 }
17 for(char c: t.toCharArray()){
18 count[c-'a']--;
19 if(count[c-'a']<0){
20 return c;
21 }
22 }
23 return ' ';
24 }
25 }
- 交替合并字符串
给你两个字符串 word1
和 word2
。请你从 word1
开始,通过交替添加字母来合并字符串。如果一个字符串比另一个字符串长,就将多出来的字母追加到合并后字符串的末尾。
返回 合并后的字符串 。
示例 1:
输入:word1 = "abc", word2 = "pqr" 输出:"apbqcr" 解释:字符串合并情况如下所示: word1: a b c word2: p q r 合并后: a p b q c r
1 class Solution {
2 public String mergeAlternately(String word1, String word2) {
3 if(word1 ==null) return word2;
4 if(word2 == null) return word1;
5
6 StringBuilder result = new StringBuilder();
7 int i=0;
8
9 while(i<word1.length() && i<word2.length()){
10 result.append(word1.charAt(i));
11 result.append(word2.charAt(i));
12 i++;
13 }
14
15 result.append(word1.substring(i));
16 result.append(word2.substring(i));
17
18 return result.toString();
19 }
20 }
- 字符串轮转
字符串轮转。给定两个字符串s1
和s2
,请编写代码检查s2
是否为s1
旋转而成(比如,waterbottle
是erbottlewat
旋转后的字符串)。
示例 1:
输入:s1 = "waterbottle", s2 = "erbottlewat" 输出:True
示例 2:
输入:s1 = "aa", s2 = "aba" 输出:False
1 class Solution {
2 public boolean isFlipedString(String s1, String s2) {
3 if(s1==null || s2==null || s1.length()!= s2.length()) {
4 return false;
5 }
6 //如果s2是s1旋转得到的,那么s2一定是s1+s1的子串
7 String doubleS1=s1+s1;
8 return doubleS1.contains(s2);
9 }
10 }
- 判断字符是否唯一
实现一个算法,确定一个字符串 s
的所有字符是否全都不同。
示例 1:
输入: s
= "leetcode"
输出: false
示例 2:
输入: s
= "abc"
输出: true
1 class Solution {
2 public boolean isUnique(String astr) {
3 if(astr.length()==1 || astr.length()==0){
4 return true;
5 }
6 for(int i=0;i<astr.length()-1;i++){
7 for(int j=i+1; j<astr.length();j++){
8 if(astr.charAt(i)==astr.charAt(j)){
9 return false;
10 }
11 }
12 }
13 return true;
14 }
15 }
- 有效的括号
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
1 class Solution {
2 public boolean isValid(String s) {
3 //如果字符串长度为奇数,肯定不匹配
4 if(s.length() %2 !=0) return false;
5
6 Stack<Character> stack =new Stack<>();
7
8 for(char c : s.toCharArray()){
9 //如果是左括号,压入栈中
10 if(c=='(' || c=='{' || c=='['){
11 stack.push(c);
12 }
13 //如果是右括号
14 else{
15 //栈为空,已经没有与之相匹配的左括号,返回不匹配
16 if(stack.isEmpty()){
17 return false;
18 }
19 //弹出栈顶元素,并匹配
20 char top=stack.pop();
21 if((c==')' && top != '(') ||
22 (c==']' && top != '[') ||
23 (c=='}' && top != '{')) {
24 return false;
25 }
26 }
27 }
28 //最终栈为空,说明全部弹出,返回匹配
29 return stack.isEmpty();
30 }
31 }
- 最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 ""
。
示例 1:
输入:strs = ["flower","flow","flight"] 输出:"fl"
示例 2:
输入:strs = ["dog","racecar","car"] 输出:"" 解释:输入不存在公共前缀。
1 class Solution {
2 public String longestCommonPrefix(String[] strs) {
3 if(strs.length==0) return "";
4
5 String ans = strs[0];
6 for(int i=1;i<strs.length;i++){
7 int j=0;
8 for(; j<ans.length() && j<strs[i].length();j++){
9 if(ans.charAt(j)!= strs[i].charAt(j))
10 break;
11 }
12 ans=ans.substring(0,j);
13 }
14 return ans;
15 }
16 }
- 罗马数字转整数
罗马数字包含以下七种字符: I
, V
, X
, L
,C
,D
和 M
。
字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000
例如, 罗马数字 2
写做 II
,即为两个并列的 1 。12
写做 XII
,即为 X
+ II
。 27
写做 XXVII
, 即为 XX
+ V
+ II
。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII
,而是 IV
。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX
。这个特殊的规则只适用于以下六种情况:
I
可以放在V
(5) 和X
(10) 的左边,来表示 4 和 9。X
可以放在L
(50) 和C
(100) 的左边,来表示 40 和 90。C
可以放在D
(500) 和M
(1000) 的左边,来表示 400 和 900。
给定一个罗马数字,将其转换成整数。
class Solution {
public int romanToInt(String s) {
Map<Character, Integer> map = new HashMap<>();
map.put('I',1);
map.put('V',5);
map.put('X',10);
map.put('L',50);
map.put('C',100);
map.put('D',500);
map.put('M',1000);
int result=0;
int previousvalue=0;
for(int i=s.length()-1; i>=0;i--){
Character currentChar = s.charAt(i);
int currentValue=map.get(currentChar);
if(currentValue < previousvalue){
result=result-currentValue;
}
else {
result=result+currentValue;
}
previousvalue=currentValue;
}
return result;
}
}
- 两数之和
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。
你可以按任意顺序返回答案。
class Solution {
public int[] twoSum(int[] nums, int target) {
int length = nums.length;
for(int i=0; i<length-1;i++){
for(int j=i+1; j<length;j++){
if(nums[i]+nums[j]==target){
return new int[]{i,j};
}
}
}
return new int[]{};
}
}
- 回文数
给你一个整数 x
,如果 x
是一个回文整数,返回 true
;否则,返回 false
。
是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
- 例如,
121
是回文,而123
不是。
class Solution {
public boolean isPalindrome(int x) {
if(x<0){
return false;
}
else {
int rev=0;
int num=x;
while(num!=0){
rev=rev*10 +num%10;
num=num/10;
}
return (rev==x);
}
}
}
- 合并两个有序数组
给你两个按 非递减顺序 排列的整数数组 nums1
和 nums2
,另有两个整数 m
和 n
,分别表示 nums1
和 nums2
中的元素数目。
请你 合并 nums2
到 nums1
中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1
中。为了应对这种情况,nums1
的初始长度为 m + n
,其中前 m
个元素表示应合并的元素,后 n
个元素为 0
,应忽略。nums2
的长度为 n
。
1 class Solution {
2 public void merge(int[] nums1, int m, int[] nums2, int n) {
3 for(int i=0; i<n; i++){
4 nums1[m+i]=nums2[i];
5 }
6 //Arrays.sort(nums1);
7
8 int len=nums1.length;
9 //外循环控制排序轮数
10 for(int i=0; i<len-1;i++){
11 //内循环进行相邻元素比较和交换
12 for(int j=0; j<len-1-i;j++){
13 //如果前面元素大于后面元素,则交换
14 if(nums1[j]>nums1[j+1]){
15 //交换元素
16 int temp = nums1[j];
17 nums1[j]=nums1[j+1];
18 nums1[j+1]=temp;
19 }
20 }
21 }
22 }
23 }
posted on 2025-09-30 22:21 LilianChen 阅读(5) 评论(0) 收藏 举报