Java — LeetCode 面试经典150题(一)

双指针

125.验证回文串

题目

如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。

字母和数字都属于字母数字字符。

给你一个字符串 s,如果它是 回文串 ,返回 true ;否则,返回 false 。

提示:

1 <= s.length <= 2e5

s 仅由可打印的 ASCII 字符组成

示例 1:
输入: s = "A man, a plan, a canal: Panama"
输出:true
解释:"amanaplanacanalpanama" 是回文串。
示例 2:
输入:s = "race a car"
输出:false
解释:"raceacar" 不是回文串。
示例 3:
输入:s = " "
输出:true
解释:在移除非字母数字字符之后,s 是一个空字符串 "" 。由于空字符串正着反着读都一样,所以是回文串。
解析:

该题是个水题,只需要移除所有非字母数字字符之后,利用双指针从新的字符串的头部和尾部不断地向对方推进,进行比较。

当两个不相同的字符时,就结束,说明此串不是回文串。

代码:
java 复制代码
class Solution {
    public boolean isPalindrome(String s) {
        String p=s.toLowerCase();
        System.out.print(p);
        char[] a=new char[p.length()];
        int len=0;
        for (int i=0;i<p.length();i++){
            if (p.charAt(i)>='a'&&p.charAt(i)<='z'||p.charAt(i)>='0'&&p.charAt(i)<='9'){
                a[len++]=p.charAt(i);
            }
        }
        boolean flag=true;
        for (int i=0,j=len-1;i<=j;i++,j--){
            if (a[i]!=a[j]){
                flag=false;
                break;
            }
        }
        return flag;
    }
}

392.判断子序列

题目

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。

字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。

提示:

0 <= s.length <= 100

0 <= t.length <= 1e4

两个字符串都只由小写字符组成。

示例 1:
输入:s = "abc", t = "ahbgdc"
输出:true
示例 2:
输入:s = "axc", t = "ahbgdc"
输出:false
解析:

遍历字符串 t,用一个指针 l 指向字符串 s 的最后一个与 s 匹配的字符的位置。

当 t[i]==s[l] 时,l++。直到遍历结束,比较 l 与字符串 s 的长度即可。

代码:
java 复制代码
class Solution {
    public boolean isSubsequence(String s, String t) {
        int n = t.length(), m = s.length();
        if (m == 0)
            return true;
        int l = 0;
        for (int i = 0; i < n; i++) {
            if (t.charAt(i) == s.charAt(l)) {
                l++;
            }
            if (l == m) {
                break;
            }
        }
        if (l == m)
            return true;
        return false;
    }
}

167.两数之和 II - 输入有序数组

题目

给你一个下标从 1 开始的整数数组 numbers ,该数组已按非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。

如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。

以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。

你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。

你所设计的解决方案必须只使用常量级的额外空间。

提示:

2 <= numbers.length <= 3 * 1e4

-1000 <= numbers[i] <= 1000 , numbers 按 非递减顺序 排列

-1000 <= target <= 1000

仅存在一个有效答案

示例 1:
输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。
示例 2:
输入:numbers = [2,3,4], target = 6
输出:[1,3]
解释:2 与 4 之和等于目标数 6 。因此 index1 = 1, index2 = 3 。返回 [1, 3] 。
示例 3:
输入:numbers = [-1,0], target = -1
输出:[1,2]
解释:-1 与 0 之和等于目标数 -1 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。
解析:

该数组已经按照非递减顺序排列,设置两个指针,分别指向数组头部和尾部。

如果指向的两个数的和小于目标数,就需要将小的那个数变大,即头部指针向后移动;反之,尾部指针向前移动。

直到两个数的和等于目标数。(仅存一个有效答案哦!)

代码
java 复制代码
class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int n=numbers.length;
        int l=0,r=n-1;
        int[] ans=new int[2];
        while (l<r){
            if (numbers[l]+numbers[r]==target){
                ans[0]=l+1;
                ans[1]=r+1;
                break;
            }
            else if (numbers[l]+numbers[r]<target){
                l++;
            }
            else{
                r--;
            }
        }
        return ans;
    }
}

11.盛最多水的容器

题目

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。

提示:

n == height.length

2 <= n <= 1e5

0 <= height[i] <= 1e4

示例 1:
输入:[1,8,6,2,5,4,8,3,7]
输出:49 
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例 2:
输入:height = [1,1]
输出:1
解析:

首先知道怎么计算水量,水量等于两个端点的距离 * 两条线较短的一条的长度。

设置两个指针指向数组的头部和尾部,一个最开始的水量就是尾部减头部的距离 * 较小的长度。

什么情况才可能比这个状态的水量大呢?就是取决于两点的距离和较短的一条线长度。

将短的那条线的指针向里面推进,只有当较短的变长了,才有可能水量变大。

这样不断推进两边端点,不断增加线的长度。每次找到后,取水量的最大值即可。

代码:
java 复制代码
class Solution {
    public int maxArea(int[] height) {
        int ans = 0;
        int l = 0, r = height.length - 1;
        while (l < r) {
            if (height[l] < height[r]) {
                ans = Math.max(ans, height[l] * (r - l));
                int t = height[l];
                while (l <= r && height[l] <= t)
                    l++;
            } else {
                ans = Math.max(ans, height[r] * (r - l));
                int t = height[r];
                while (l <= r && height[r] <= t)
                    r--;
            }
        }
        return ans;
    }
}
 

15.三数之和

题目

给你一个整数数组 nums ,判断是否存在三元组[nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。

请你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

提示:

3 <= nums.length <= 3000

-1e5 <= nums[i] <= 1e5

示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。
示例 2:
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。
示例 3:
输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。
解析:

首先,数据最大是3000,所以双for循环不会超时,所以用双for循环遍历nums[i]和nums[j],那么关于剩下的数就是判断0-nums[i]-nums[j]是否在数组中了,我是用的map,将数组中的数和它的坐标存在map对象中,判断该数是否存在且不是第i个数也不是第j个数。

然后就是去重问题,我将符合条件的三个数,存放进一个数组中,进行sort。然后将数组的三个数放进List中,将List放进一个Set中,进行去重。(有更简便的算法,我这个是更加合理地使用集合的那些容器)

代码:
java 复制代码
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Set<List<Integer>> res = new HashSet<>();
        Map<Integer, Integer> m = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            m.put(nums[i], i);
        }
        for (int i = 0; i < nums.length; i++)
            for (int j = i + 1; j < nums.length; j++) {
                int k = 0 - nums[i] - nums[j];
                if (m.containsKey(k) && m.get(k) != i && m.get(k) != j) {
                    List<Integer> s = new ArrayList<>();
                    int[] a = new int[3];
                    a[0] = nums[i];
                    a[1] = nums[j];
                    a[2] = k;
                    Arrays.sort(a);
                    s.add(a[0]);
                    s.add(a[1]);
                    s.add(a[2]);
                    res.add(s);
                }
            }
        return new ArrayList<List<Integer>>(res);
    }
}
相关推荐
古希腊掌管学习的神12 分钟前
[搜广推]王树森推荐系统笔记——曝光过滤 & Bloom Filter
算法·推荐算法
qystca13 分钟前
洛谷 P1706 全排列问题 C语言
算法
古希腊掌管学习的神18 分钟前
[LeetCode-Python版]相向双指针——611. 有效三角形的个数
开发语言·python·leetcode
浊酒南街19 分钟前
决策树(理论知识1)
算法·决策树·机器学习
V+zmm1013424 分钟前
基于微信小程序的乡村政务服务系统springboot+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm
就爱学编程26 分钟前
重生之我在异世界学编程之C语言小项目:通讯录
c语言·开发语言·数据结构·算法
学术头条31 分钟前
清华、智谱团队:探索 RLHF 的 scaling laws
人工智能·深度学习·算法·机器学习·语言模型·计算语言学
Oneforlove_twoforjob1 小时前
【Java基础面试题025】什么是Java的Integer缓存池?
java·开发语言·缓存
xmh-sxh-13141 小时前
常用的缓存技术都有哪些
java
Schwertlilien1 小时前
图像处理-Ch4-频率域处理
算法