▊【Q22】(md) 括号生成
数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
示例:
输入:
n = 3
输出:[
“((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”
]
class Solution {
/*
* 【回溯算法】
* 思路 :其实这是很典型的需要减枝的回溯算法,应该不难想到
*
* 这类回溯算法与递归回溯不同,逻辑优美巧妙且简单;下面简单说一下回溯方法 traceBack的参数 :
*
* int n 是每一层都需要的信息(要用于判断回溯的终止(回头)条件)
* String tempString 暂存串,不必多说
* int L, int R 是用于减枝的(右括号不可能多于左括号)
*/
public List<String> generateParenthesis(int n) {
traceBack(n, "", 0, 0);
return resList;
}
public List<String> resList = new ArrayList<>();
public void traceBack(int n, String tempString, int L, int R) {
if(R + L == 2*n) {
if( R == n && L == n) {
resList.add(tempString.toString());
return;
}else {
return;// 减枝
}
}
if(L < R) {
return;// 减枝
}
traceBack(n, tempString + "(", L+1, R);
traceBack(n, tempString + ")", L, R+1);
}
}
▊【Q26】(ez) 删除数组的中的重复项
给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
示例 1:给定数组 nums = [1,1,2],
函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。
你不需要考虑数组中超出新长度后面的元素。
示例 2:给定 nums = [0,0,1,1,1,2,2,3,3,4],
函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。
你不需要考虑数组中超出新长度后面的元素。
class Solution {
public int removeDuplicates(int[] nums) {
/*
* 覆盖的思想,很简单
* 题目说了很多,其实就是在引导与暗示我们使用覆盖的思想
*/
if(nums == null || nums.length == 0) return 0;
int len = 0;
for(int i = 0 ; i < nums.length ; i++) {
if( i > 0 && nums[i] == nums[i-1]) {
continue;
}else {
nums[len++] = nums[i];
}
}
return len;
}
}
class Solution {
public int removeDuplicates(int[] nums) {
/*
* 通过现象看本质,我们随手写出的代码,其实利用了一个经典的算法思想:
* 【双指针】
* 在上面那段代码中,len是一个"慢指针",i是"快指针",它们从同一侧开始同向移动
*
* 把它们分别换成 i, j后,双指针思想便显而易见了:
*/
if(nums == null || nums.length == 0) return 0;
int i = 0;
int j = 0;
for( ; j < nums.length ; j++) {
if( j > 0 && nums[j] == nums[j-1]) {
continue;
}else {
nums[i++] = nums[j];
}
}
return i;
}
}
预警 !
Warning !
KMP
算法预警 ! ! !
▊【Q28】(hd) 实现 strStr(即indexOf)
实现 strStr() 函数。
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置(从0开始)。如果不存在,则返回 -1。
示例 1:输入: haystack = “hello”, needle = “ll”
输出: 2
示例 2:输入: haystack = “aaaaa”, needle = “bba”
输出: -1
说明:当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。
class Solution {
public int strStr(String haystack, String needle) {
/*
* 【KMP算法】
* 简单说一下我浅薄的理解吧!
* KMP算法用于字符串的匹配
* 该算法分为两部分,但两部分的核心精髓相同
* 一是根据模式串,生成next数组(★★★)
* 二是用模式串去匹配主串,在匹配失败时根据next数组进行回溯(回退),而不是直接退到模式串的0索引
*
* 这是典型的空间换时间
*/
if(needle == null || needle.length() == 0) return 0;
char[] t = haystack.toCharArray();
char[] p = needle.toCharArray();
int i = 0; // 主串位置
int j = 0; // 模式串位置
int[] next = getNext(needle);
while(i < t.length && j < p.length) {
if(j == -1 || t[i] == p[j]) { //当j为-1时,要移动的是i,当然j也要归零
i++;
j++; // 相同则两串的指针都递增
}else {
j = next[j]; // 不同则j回到指定位置
}
}
if(j == p.length) {
return i - j;
}else {
return -1;
}
}
public static int[] getNext(String needle) {
char[] p = needle.toCharArray();
int[] next = new int[p.length];
next[0] = -1;
int j = 0; // p数组的下标
int k = -1; // 修正过的最大相同前后缀长度
while(j < p.length - 1) {
if(k == -1 || p[j] == p[k]) {
j++;
k++;
if(p[j] == p[k]) { // 这里对next数组进行了优化
next[j] = next[k]; // 如果p[j + 1] == p[k + 1],回退后仍然失配,所以要继续回退
}else {
next[j] = k;
}
}else {
k = next[k]; // 回退
}
}
return next;
}
// 未优化的next数组
public static int[] getNext2(String needle) {
char[] p = needle.toCharArray();
int[] next = new int[p.length];
next[0] = 0;
int j = 1; // p数组的下标
int k = 0; // 最大相同前后缀长度
for( ; j < p.length ; j++) {
while(k > 0 && p[j] != p[k]) k = next[k - 1]; // 回退
if(p[j] == p[k]) k++;
next[j] = k;
}
return next;
}
}
Qs from https://leetcode-cn.com
♥ loli suki
♠ end