▊【Q17】(md) 电话号码的字母组合
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:输入:“23”
输出:[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].
说明:
尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。
class Solution {
/*
* 【回溯法】
* 思路:首先想到for语句嵌套,但其数量不确定,且时间复杂度爆炸
* 对于这种次数不固定的嵌套,应该马上反应过来这是回溯问题
*
*/
public List<String> letterCombinations(String digits) {
if(digits == null || digits.length() == 0) return new ArrayList<String>(); // leetcode总会有空值test
traceBack(digits, "", 0);
return resList;
}
String[] letterMap = {
" ", " ", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; // 按键对应“字母块”的字典
List<String> resList = new ArrayList<String>();
public void traceBack(String digits, String letter, int index) {
/*
* ★★★写出这个回溯方法是重点,难点,也是巧妙之处
*
* 三个参数:
* ▷ digits是输入的字符串,每一层中需要通过index取出一个数字,来索引到那个"字母块"
* ▷ letter是关键!用于暂存已经遍历到的字母串
* ▷ index用于索引取出digits的某个数字,index随着层数变动
*
* 回溯方法的停止条件(开始回溯)、如何给下一层traceback传参,更是该算法的灵魂
* ▷ 停止(并开始回溯)的条件是:index=length,index已经等于层数(输入字符串数字的个数)
* 此时暂存串letter已经完全,把它add到最终结果resList中
* ▷ 传参:digits作为一个参考不需要改变,改变是索引它的那个index,也就是层数;
* letter暂存串加上此层次上读取的字母
*/
if(index == digits.length()) {
resList.add(letter);
return;
}
char c = digits.charAt(index);
int temp = Integer.valueOf(String.valueOf(c));
String letterPart = letterMap[temp]; // 上面这三行,是为了找到这一层的数字对应的“字母块”letterPart
for(int i = 0 ; i < letterPart.length() ; i++) {
traceBack(digits, letter + letterPart.charAt(i), index + 1);
}
}
// 总结:
// ★☆★ 其实实现回溯的根源在于traceback方法的for语句
// ★☆★ 暂存串暂存了这一条“试探”路径,也是实现此算法的关键
// ★☆★ 回溯是很重要很重要很重要很重要的算法,背也要背会
}
▊【Q14】(ez) 最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。
示例 1:输入: [“flower”,“flow”,“flight”]
输出: “fl”
示例 2:输入: [“dog”,“racecar”,“car”]
输出: “” 解释: 输入不存在公共前缀。
说明:所有输入只包含小写字母 a-z 。
class Solution {
/*
* 暴力法就是选取一个字符串,置指针指向第一个,然后所有字符串首字母与其比较;若全部相同,指针+1后进行下一轮比较
* 但这种方法不仅效率低下,还需要对越界问题进行处理,代码量不低
* 以下的思路比较巧妙:
* 选取一个字符串作为操作基准,不断割短这个字符串,直到它是所有字符串的开头为止
*/
public String longestCommonPrefix(String[] strs) {
if(strs.length == 0) return "";
String s = strs[0];
for(String each : strs) {
while(each.indexOf(s) != 0) {
s = s.substring(0, s.length()-1); // "不断割短这个字符串,直到它是所有字符串的开头为止"
}
}
return s;
}
// 总结:
// 遇到ez等级的题目,尽量抛弃脑中瞬间浮现的第一个暴力法
}
▊【Q18】(md) 四数之和问题
给定一个包含 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] ]
class Solution_18 {
public List<List<Integer>> fourSum(int[] nums, int target) {
/*
* 【双指针算法】
* 之前详细分析了"三数之和问题",那是一个经典的三项双指针,此题是四项双指针
*
* 思路类似:
* 在"三数之和问题"中,for语句中为i,然后固定i、移动收缩双指针L,R
* 而在此题中,两个for语句嵌套(i,j一左一右),然后固定i,j、移动收缩双指针L,R
*
* 细节同样有两处:
* 一是去重;二是在去重时防止越界
*/
List<List<Integer>> resList = new ArrayList<>();
if(nums == null || nums.length < 4 ) return resList;
Arrays.sort(nums);
int len = nums.length;
for(int i = 0 ; i < len - 3 ; i++) {
if(i > 0 && nums[i] == nums[i - 1]) continue; // 去重
for(int j = len - 1 ; j > i ; j--) {
if(j < len-1 && nums[j] ==nums[j + 1] ) continue; // 去重
int L = i + 1;
int R = j - 1;
while(L < R && i < j) {
int sum = nums[i] + nums[L] + nums[R] + nums[j];
if(sum == target) {
resList.add(Arrays.asList(nums[i], nums[L], nums[R], nums[j]));
while(L < R && nums[L] == nums[L + 1]) L++; // 去重(注意写上L
while(L < R && nums[R] == nums[R - 1]) R--; // 去重
L++;
R--;
}else if(sum < target) {
L++;
}else if(sum > target) {
R--;
}
}
}
}
return resList;
}
}
▊【Q20】(ez) 有效的括号(括号匹配问题)
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]'的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 注意空字符串可被认为是有效字符串。
示例 1:
输入: “([{}])”
输出: true
示例 2:
输入: “([)]”
输出: false
class Solution_19 {
public boolean isValid(String s) {
/*
* 思路:
* 1.使用HashMap进行匹配,使得代码和逻辑都更具美感
* 2.典型的栈结构问题。由于java 8,9有移除Stack的趋势,因此这里使用双端队列Deque,同样有PushPop特性
*/
if(s == null || s.length() == 0) return true; // leetcode传统艺能,null和0值不说就是true
Map<Character, Character> map = new HashMap<>();
map.put(')', '(');
map.put(']', '[');
map.put('}', '{');
Deque<Character> dq = new ArrayDeque<>();
for(char c : s.toCharArray()){
if(c == '(' || c == '[' || c == '{'){
dq.push(c);
}else{
if(dq.size() == 0 || map.get(c) != dq.pop()) return false;
}
}
return dq.size() == 0;
}
}
Qs from https://leetcode-cn.com
♣ loli suuuki
♥ end