LeetCode 0-50 整理(Java)
range(0, 10)
range(10, 20)
15 三数之和
- 中等
https://leetcode-cn.com/problems/3sum/
给你一个包含 n
个整数的数组 nums
,判断 nums
中是否存在三个元素
\(a,b,c\) ,使得 \(a + b + c = 0\) ?请你找出所有和为
0
且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
示例 2:
输入:nums = []
输出:[]
示例 3:
输入:nums = [0]
输出:[]
提示:
- \(0 <= nums.length <= 3000\)
- \(-10^5 <= nums[i] <= 10^5\)
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
int len = nums.length;
if (nums == null || len < 3)
return result;
Arrays.sort(nums);
for (int i = 0; i < len; i++) {
if (nums[i] > 0)
break;
if (i > 0 && nums[i] == nums[i - 1]) // 去重
continue;
// 双指针
int L = i + 1;
int R = len - 1;
while (L < R) {
int sum = nums[i] + nums[L] + nums[R];
if (sum == 0) {
result.add(Arrays.asList(nums[i], nums[L], nums[R]));
while (L < R && nums[L] == nums[L + 1])
L++;
while (L < R && nums[R] == nums[R - 1])
R--;
L++;
R--;
} else if (sum < 0) {
L++;
} else if (sum > 0) {
R--;
}
}
}
return result;
}
}
16 最接近的三数之和
https://leetcode-cn.com/problems/3sum-closest/
- 中等
给定一个包括 n
个整数的数组 nums
和
一个目标值 target
。找出 nums
中的三个整数,使得它们的和与 target
最接近。返回这三个数的和。假定每组输入只存在唯一答案。
示例:
输入:nums = [-1,2,1,-4], target = 1
输出:2
解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
提示:
- \(3 <= nums.length <= 10^3\)
- \(-10^3 <= nums[i] <= 10^3\)
- \(-10^4 <= target <= 10^4\)
class Solution {
public int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);
int ans = nums[0] + nums[1] + nums[2];
for (int i = 0; i < nums.length; i++) {
int start = i + 1;
int end = nums.length -1;
while (start < end) {
int sum = nums[i] + nums[start] + nums[end];
if (Math.abs(target - sum) < Math.abs(target - ans)) {
ans = sum;
}
if (sum > target) {
end--;
} else if (sum < target) {
start ++;
} else {
return ans;
}
}
}
return ans;
}
}
17 电话号码的字母组合
https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例 1:
输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
示例 2:
输入:digits = ""
输出:[]
示例 3:
输入:digits = "2"
输出:["a","b","c"]
提示:
0 <= digits.length <= 4
digits[i]
是范围['2', '9']
的一个数字。
class Solution {
public List<String> letterCombinations(String digits) {
// 定义数字键盘对应的字典字母表
char[][] abc = {{'a','b','c'},{'d','e','f'},{'g','h','i'}
,{'j','k','l'},{'m','n','o'},{'p','q','r','s'}
,{'t','u','v'},{'w','x','y','z'}};
// 定义队列 ,辅助拼接字母
LinkedList<String> ans = new LinkedList<>();
if (digits.isEmpty()) {
return ans;
}
// 初始化队列中最开始还没拼接字母的空字符串
ans.add("");
// 从源数字字符串第一个字符开始遍历
for (int i = 0; i < digits.length(); i++) {
// 获取当前数值字符对应到字母表中的角标
int num = Character.getNumericValue(digits.charAt(i)) - 2; // 将字符转换成数字,而非ASCII码
// 当队列中所有字符串的长度等于当前遍历到的数字字符个数,则本轮拼接完成
while (ans.peek().length() < i + 1) { // peak函数:检索但不删除此列表的头
// 依次取出队列中所有的字符串
String s = ans.remove(); // 检索并删除此列表的头(第一个元素)
// 每个字符串循环拼接当前数字字符对应的所有字母后再加入队列
for (char c : abc[num]) {
ans.add(s + c);
}
}
}
return ans;
}
}
18 四数之和
- 中等
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] :
- 0 <= a, b, c, d < n
- a、b、c 和 d 互不相同
- nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。
示例 1:
输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
示例 2:
输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]
提示:
- 1 <= nums.length <= 200
- \(-10^9\) <= nums[i] <= \(10^9\)
- \(-10^9\) <= target <= \(10^9\)
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
List<List<Integer>> result = new ArrayList<>();
if (nums == null || nums.length < 4) {
return result;
}
int minValue = nums[0] + nums[1] + nums[2] + nums[3];
int maxValue = nums[nums.length - 1] + nums[nums.length - 2] + nums[nums.length - 3] + nums[nums.length - 4];
if (minValue > target || maxValue < target) {
return result;
}
for (int i = 0; i < nums.length - 3; i++) {
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
for (int j = i + 1; j < nums.length - 2; j++) {
if (j > i + 1 && nums[j] == nums[j - 1]) {
continue;
}
int left = j + 1;
int right = nums.length - 1;
minValue = nums[i] + nums[j] + nums[left] + nums[left + 1];
maxValue = nums[i] + nums[j] + nums[right] + nums[right - 1];
if (minValue > target || maxValue < target) {
continue;
}
while (left < right) {
int temp = nums[left] + nums[right] + nums[i] + nums[j];
if (temp == target) {
List<Integer> l = new ArrayList<>(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
result.add(l);
while (left < right && nums[left] == nums[left + 1]) {
left++;
}
while (left < right && nums[right] == nums[right - 1]) {
right--;
}
left++;
right--;
} else if (temp > target) {
right--;
} else {
left++;
}
}
}
}
return result;
}
}
19 删除链表的倒数第 N 个结点
- 中等
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
进阶:你能尝试使用一趟扫描实现吗?
示例 1:
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例 2:
输入:head = [1], n = 1
输出:[]
示例 3:
输入:head = [1,2], n = 1
输出:[1]
提示:
- 链表中结点的数目为
sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
if (head == null || head.next == null) {
return null;
}
ListNode fast = head;
ListNode slow = head;
for (int i = 0; i < n; i++) {
fast = fast.next;
}
// 删第一个节点的情况
if (fast == null) {
return head.next;
}
while (fast.next != null) {
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return head;
}
}
20 有效的括号
- 简单
给定一个只包括 '(',')','{','}','[',']'
的字符串
s
,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
示例 1:
输入:s = "()"
输出:true
示例 2:
输入:s = "()[]{}"
输出:true
示例 3:
输入:s = "(]"
输出:false
示例 4:
输入:s = "([)]"
输出:false
示例 5:
输入:s = "{[]}" 输出:true
提示:
- 1 <= s.length <= \(10^4\)
s
仅由括号'()[]{}'
组成
class Solution {
public boolean isValid(String s) {
if (s.isEmpty()) {
return true;
}
Stack<Character> stack = new Stack<>(); // 创建一个堆栈
for (char c : s.toCharArray()) {
if (c == '(') {
stack.push(')');
} else if (c == '[') {
stack.push(']');
} else if (c == '{') {
stack.push('}');
} else if (stack.empty() || c != stack.pop()) {
return false;
}
}
return stack.empty();
}
}