软件测试工程师面试刷题:简单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 }

 

  • 字符串轮转

字符串轮转。给定两个字符串s1s2,请编写代码检查s2是否为s1旋转而成(比如,waterbottleerbottlewat旋转后的字符串)。

示例 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. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。
 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, LCD 和 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)    收藏  举报

导航