016 最接近的三数之和
题目描述
给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.
与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).
解题思路
public static int threeSumClosest(int[] nums, int target) {
// 排序
Arrays.sort(nums);
int closestNum = nums[0] + nums[1] + nums[2];
for (int i = 0; i < nums.length - 2; i++) {
int l = i + 1, r = nums.length - 1;
while (l < r) {
int threeSum = nums[l] + nums[r] + nums[i];
if (Math.abs(threeSum - target) < Math.abs(closestNum - target)) {
closestNum = threeSum;
}
if (threeSum > target) {
r--;
} else if (threeSum < target) {
l++;
} else {
// 如果已经等于target的话, 肯定是最接近的
return target;
}
}
}
return closestNum;
}
017 电话号码的字母组合
题目描述
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:
输入:"23"
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
说明:
尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。
解题思路
static String[][] letters = {{"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"}
};
public static List<String> letterCombinations(String digits) {
List<String> result = new ArrayList<>();
if (digits == null || digits.length() == 0) {
return result;
}
char[] chars = digits.toCharArray();
for (char c : chars) {
int idx = c - 48;
String[] str = letters[idx - 2];
if (result.size() > 0) {
int size = result.size();
for (int i = 0; i < size; i++) {
String s = result.get(i);
result.set(i, s + str[0]);
for (int j = 1; j < str.length; j++) {
result.add(size , s + str[j]);
}
}
} else {
result.addAll(Arrays.asList(str));
}
}
Collections.sort(result);
return result;
}
018 四数之和
题目描述
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,**b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
注意:
答案中不可以包含重复的四元组。
示例:
给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。
满足要求的四元组集合为:
[
[-1, 0, 0, 1],
[-2, -1, 1, 2],
[-2, 0, 0, 2]
]
解题思路
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> res = new ArrayList<>();
if (nums == null || nums.length < 4) {
return res;
}
Arrays.sort(nums);
for (int i = 0; i < nums.length; i++) {
// 对第一重元素去重处理
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
for (int j = i + 1; j < nums.length; j++) {
// 对第二重元素去重
if (j > i + 1 && nums[j] == nums[j - 1]) {
continue;
}
int p = j + 1;
int q = nums.length - 1;
while (p < q) {
int sum = nums[i] + nums[j] + nums[p] + nums[q];
if (sum == target) {
List<Integer> list = new ArrayList<>();
list.add(nums[i]);
list.add(nums[j]);
list.add(nums[p]);
list.add(nums[q]);
res.add(list);
// 对第三重元素去重操作
while (p < q && nums[p] == nums[p + 1]) {
p++;
}
while (p < q && nums[q] == nums[q - 1]) {
q--;
}
p++;
q--;
} else if (sum < target) {
p++;
} else {
q--;
}
}
}
}
return res;
}
019 删除链表的倒数第n个节点
题目描述
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
进阶:
你能尝试使用一趟扫描实现吗?
解题思路
public static ListNode removeNthFromEnd(ListNode head, int n) {
ListNode p = head;
ListNode st = new ListNode(-1);
st.next = head;
ListNode q = st;
int i = 0, j = 0;
while (p.next != null) {
j++;
if (j - i == n) {
i++;
q = q.next;
}
p = p.next;
}
q.next = q.next.next;
return st.next;
}
020 有效的括号
题目描述
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
示例 1:
输入: "()"
输出: true
示例 2:
输入: "()[]{}"
输出: true
示例 3:
输入: "(]"
输出: false
示例 4:
输入: "([)]"
输出: false
示例 5:
输入: "{[]}"
输出: true
解题思路
static Map<Character,Character> map = new HashMap<>();
static{
map.put('(',')');
map.put('{','}');
map.put('[',']');
}
public boolean isValid(String s) {
if(s == null || s.length() == 0){
return true;
}
char[] arr = s.toCharArray();
Stack<Character> stack = new Stack<>();
for(char c : arr){
if(c == '(' || c == '{' || c == '['){
stack.push(c);
}else{
if(stack.isEmpty() || map.get(stack.pop()) != c)
return false;
}
}
return stack.isEmpty();
}