15 三数之和
15. 三数之和 - 力扣(LeetCode) (leetcode-cn.com)
给你一个包含 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]
输出:[]
是 a+b+c = 0
数组排序, 一个指针 从左往右走 当前位置的数 i ,i位置得数当作三元组得第一个数,在 后边 找 和在 (0-nums[i]) 得一个二元组
当 i 来到下一个位置得时候 发现跟前面得数一样直接跳过
例: -5,-5,-5,-1,0,1,5… 当来到第一个 -5 得时候 在来到第二个-5可以直接跳过,因为在第一个-5得时候 就把 以-5 第一个数得,所有得二元组都求过了
不需要在以 第二个 -5 去求
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> ans = new ArrayList<>();
for (int i = 0; i < nums.length - 2; i++) {
if (i == 0 || nums[i - 1] != nums[i]) {
List<List<Integer>> two = twoSum(nums, i + 1, -nums[i]);
for (List<Integer> cur : two) {
cur.add(0, nums[i]);
ans.add(cur);
}
}
if (nums[i] > 0){ //因为数组是排好序的 i后边的数 都是 大于它的
return ans;
}
}
return ans;
}
// nums已经有序了
public static List<List<Integer>> twoSum(int[] nums, int start, int target) {
int L = start;
int R = nums.length - 1;
List<List<Integer>> ans = new ArrayList<>();
while (L < R) {
if (nums[L] + nums[R] > target) {
R--;
} else if (nums[L] + nums[R] < target) {
L++;
} else {//相等, 保证你左边的数和当前的数 不相等
if (L == start || nums[L - 1] != nums[L]) {
List<Integer> cur = new ArrayList<>();
cur.add(nums[L]);
cur.add(nums[R]);
ans.add(cur);
}
L++;
}
}
return ans;
}
17 电话号码的字母组合
17. 电话号码的字母组合 - 力扣(LeetCode) (leetcode-cn.com)
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例 1:
输入:digits = “23”
输出:[“ad”,“ae”,“af”,“bd”,“be”,“bf”,“cd”,“ce”,“cf”]
示例 2:
输入:digits = “”
输出:[]
示例 3:
输入:digits = “2”
输出:[“a”,“b”,“c”]
每条路线都走一下
static char[][] p = {
{'a', 'b', 'c'}, // 2 0
{'d', 'e', 'f'}, // 3 1
{'g', 'h', 'i'}, // 4 2
{'j', 'k', 'l'}, // 5 3
{'m', 'n', 'o'}, // 6 4
{'p', 'q', 'r', 's'}, // 7 5
{'t', 'u', 'v'}, // 8 6
{'w', 'x', 'y', 'z'}, // 9 7
};
public List<String> letterCombinations(String digits) {
List<String> ans = new ArrayList<>();
if (digits == null || digits.length() == 0) {
return ans;
}
char[] str = digits.toCharArray();
char[] path = new char[str.length];//path 之前按出的结果
process(str, 0, path, ans);
return ans;
}
public static void process(char[] str, int index, char[] path, List<String> ans) {
if (index == str.length) {
ans.add(String.valueOf(path));
} else {
char[] chars = p[str[index] - '2'];
for (char cur : chars) {
path[index] = cur; //当前字符 的每种路线都走一下
process(str,index+1,path,ans);
}
}
}
19 删除链表的倒数第N个节点
19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode) (leetcode-cn.com)
给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
进阶你能尝试使用一趟扫描实现吗?
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例 2:
输入:head = [1], n = 1
输出:[]
示例 3:
输入:head = [1,2], n = 1
输出:[1]
双指针,先数出来 n个 然后 双指针,一起移动 到达尾部的时候,另外一个就是倒数第N个节点 ,但是删掉节点 是要找到他的前一个节点,指向它的下一个
就是 要删除节点的前一个。
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode cur = head;
ListNode pre = null;
boolean flag = false;
while (cur != null) {//结束 之后 pre就是 要删除的 前一个
n--;
if (n <= 0) {
if (n == 0) {
flag = true; //已经 n 个数了
} else if (n == -1) {//此时标记 pre
pre = head;
} else {
pre = pre.next;
}
}
cur = cur.next;
}
if (!flag) {//够不够
return head;
}
if (pre == null) {//说明要删除的是 头节点
return head.next;
}
pre.next = pre.next.next;
return head;
}
20 有效的括号
20. 有效的括号 - 力扣(LeetCode) (leetcode-cn.com)
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
示例 1:
输入:s = “()”
输出:true
示例 2:
输入:s = “()[]{}”
输出:true
示例 3:
输入:s = “(]”
输出:false
示例 4:
输入:s = “([)]”
输出:false
示例 5:
输入:s = “{[]}”
输出:true
栈,遇到左括号 入栈,右括号弹,匹配上继续,匹配不上 拜拜,最后栈为空。
public boolean isValid(String s) {
if (s == null || s.length() == 0) {
return true;
}
char[] str = s.toCharArray();
Stack<Character> stack = new Stack<>();
for (int i = 0; i < str.length; i++) {
char c = str[i];
if (c == '(' || c == '[' || c == '{') {
stack.add(c == '(' ? ')' : (c == '[' ? ']' : '}'));
} else {
if (stack.isEmpty()) {
return false;
}
char last = stack.pop();
if (c != last) {
return false;
}
}
}
return stack.isEmpty();
}