LeetCode 100道题目和答案(面试必备)(一)

1.两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。
在这里插入图片描述

class Solution {
   
    public int[] twoSum(int[] nums, int target) {
   
        int n = nums.length;
        for (int i = 0; i < n; ++i) {
   
            for (int j = i + 1; j < n; ++j) {
   
                if (nums[i] + nums[j] == target) {
   
                    return new int[]{
   i, j};
                }
            }
        }
        return new int[0];
    }
}
方法二:哈希表
思路及算法
注意到方法一的时间复杂度较高的原因是寻找 target - x 的时间复杂度过高。因此,我们需要一种更优秀的方法,能够快速寻找数组中是否存在目标元素。如果存在,我们需要找出它的索引。
使用哈希表,可以将寻找 target - x 的时间复杂度降低到从 O(N)O(N) 降低到 O(1)O(1)。
这样我们创建一个哈希表,对于每一个 x,我们首先查询哈希表中是否存在 target - x,然后将 x 插入到哈希表中,即可保证不会让 x 和自己匹配。
class Solution {
   
    public int[] twoSum(int[] nums, int target) {
   
        Map<Integer, Integer> hashtable = new HashMap<Integer, Integer>();
        for (int i = 0; i < nums.length; ++i) {
   
            if (hashtable.containsKey(target - nums[i])) {
   
                return new int[]{
   hashtable.get(target - nums[i]), i};
            }
            hashtable.put(nums[i], i);
        }
        return new int[0];
    }
}
2.回文数

给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。

回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。

在这里插入图片描述

答案:

class Solution {
   
    public boolean isPalindrome(int x) {
   
        // 特殊情况:
        // 如上所述,当 x < 0 时,x 不是回文数。
        // 同样地,如果数字的最后一位是 0,为了使该数字为回文,
        // 则其第一位数字也应该是 0
        // 只有 0 满足这一属性
        if (x < 0 || (x % 10 == 0 && x != 0)) {
   
            return false;
        }

        int revertedNumber = 0;
        while (x > revertedNumber) {
   
            revertedNumber = revertedNumber * 10 + x % 10;
            x /= 10;
        }

        // 当数字长度为奇数时,我们可以通过 revertedNumber/10 去除处于中位的数字。
        // 例如,当输入为 12321 时,在 while 循环的末尾我们可以得到 x = 12,revertedNumber = 123,
        // 由于处于中位的数字不影响回文(它总是与自己相等),所以我们可以简单地将其去除。
        return x == revertedNumber || x == revertedNumber / 10;
    }
}
3.罗马数字转整数

在这里插入图片描述在这里插入图片描述

方法一:模拟
思路
通常情况下,罗马数字中小的数字在大的数字的右边。若输入的字符串满足该情况,那么可以将每个字符视作一个单独的值,累加每个字符对应的数值即可。
若存在小的数字在大的数字的左边的情况,根据规则需要减去小的数字。对于这种情况,我们也可以将每个字符视作一个单独的值,若一个数字右侧的数字比它大,则将该数字的符号取反。
class Solution {
   
    Map<Character, Integer> symbolValues = new HashMap<Character, Integer>() {
   {
   
        put('I', 1);
        put('V', 5);
        put('X', 10);
        put('L', 50);
        put('C', 100);
        put('D', 500);
        put('M', 1000);
    }};

    public int romanToInt(String s) {
   
        int ans = 0;
        int n = s.length();
        for (int i = 0; i < n; ++i) {
   
            int value = symbolValues.get(s.charAt(i));
            if (i < n - 1 && value < symbolValues.get(s.charAt(i + 1))) {
   
                ans -= value;
            } else {
   
                ans += value;
            }
        }
        return ans;
    }
}
4.最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 ""
在这里插入图片描述

class Solution {
   
    public String longestCommonPrefix(String[] strs) {
   
        if (strs == null || strs.length == 0) {
   
            return "";
        }
        String prefix = strs[0];
        int count = strs.length;
        for (int i = 1; i < count; i++) {
   
            prefix = longestCommonPrefix(prefix, strs[i]);
            if (prefix.length() == 0) {
   
                break;
            }
        }
        return prefix;
    }

    public String longestCommonPrefix(String str1, String str2) {
   
        int length = Math.min(str1.length(), str2.length());
        int index = 0;
        while (index < length && str1.charAt(index) == str2.charAt(index)) {
   
            index++;
        }
        return str1.substring(0, index);
    }
}
public static String re(String[] str){
   
    if(str.length==0){
   
        return "";
    }
    String str1=str[0];
    for (int i = 1; i < str.length; i++) {
   
        str1 = bj(str1, str[i]);
    if (str1.length()==0){
   
        break;
    }
    //当第一个没有比对上时,直接用break结束循环,减少时间。
    }
    if (str1.length()==0){
   
        return "";
    }
    return str1;
}

private static String bj(String str2, String str3) {
   
    int min = Math.min(str2.length(), str3.length());
    int index=0;
    while (index<min&&str2.charAt(index)==str3.charAt(index)){
   
        index++;
    }
    //用while比for循环次数更少
    return str2.substring(0,index);
}

public static void main(String[] args) {
   
    String[] str=new String[]{
   "moyon","molon","moxue"};
    String result = re(str);
    System.out.println(result);
}
5.删除有序数组中的重复项

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

在这里插入图片描述

答案:

解法: 双指针
首先注意数组是有序的,那么重复的元素一定会相邻。
要求删除重复元素,实际上就是将不重复的元素移到数组的左侧。
考虑用 2 个指针,一个在前记作 p,一个在后记作 q,算法流程如下:
1.比较 p 和 q 位置的元素是否相等。
如果相等,q 后移 1 位
如果不相等,将 q 位置的元素复制到 p+1 位置上,p 后移一位,q 后移 1 位
重复上述过程,直到 q 等于数组长度。
返回 p + 1,即为新数组长度。
 public int removeDuplicates(int[] nums) {
   
    if(nums == null || nums.length == 0) return 0;
    int p = 0;
    int q = 1;
    while(q < nums.length){
   
        if(nums[p] != nums[q]){
   
            nums[p + 1] = nums[q];
          
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值