28. 实现 strStr()
算法链接:
28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)
类型: 字符串
难度: 简单
思路:KMP算法:当出现字符串不匹配时,可以记录一部分之前已经匹配的文本内容,利用这些信息避免从头再去做匹配。
前缀表(next数组):前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配的时候,模式串应该从哪里开始重新匹配。
第一步:构造needle长度的next数组和模式串:
(1)下标j与i不相等发生冲突时(循环): j = next[j - 1];
(2)下标j与i相等时(if判断):j++;
(3)最后赋值:next[i] = j;
第二步 :遍历haystack字符串(索引下标为i),next数组(下标为j):
(1)下标j与i不相等发生冲突时(循环): j = next[j - 1];
(2)下标j与i相等时(if判断):j++;
(3)最后判断:j是否与needle长度相等,true则返回i - needle.length() + 1;
总结:KMP算法不等j向后循环,相等j++;
题解:
class Solution {
//前缀表(不减一)Java实现
public int strStr(String haystack, String needle) {
if (needle.length() == 0) return 0;
int[] next = new int[needle.length()];
getNext(next, needle);
int j = 0;
for (int i = 0; i < haystack.length(); i++) {
while (j > 0 && needle.charAt(j) != haystack.charAt(i))
j = next[j - 1];
if (needle.charAt(j) == haystack.charAt(i))
j++;
if (j == needle.length())
return i - needle.length() + 1;
}
return -1;
}
private void getNext(int[] next, String s) {
int j = 0;
next[0] = 0;
for (int i = 1; i < s.length(); i++) {
while (j > 0 && s.charAt(j) != s.charAt(i))
j = next[j - 1];
if (s.charAt(j) == s.charAt(i))
j++;
next[i] = j;
}
}
}
459.重复的子字符串
算法链接:
类型: 字符串
难度: 简单
思路:找到最长的相等前后缀子字符串,构建前缀表,最后判断是否有重复子字符串,主字符串长度是否为子字符串的整数倍,是则表明有重复的子字符串。
题解:
class Solution {
public boolean repeatedSubstringPattern(String s) {
if(s.equals("")) return false;
int len = s.length();
s = " " + s;
char[] chars = s.toCharArray();
int[] next = new int[len + 1];
for(int i = 2,j = 0;i <= len; i++){
while(j > 0 && chars[i] != chars[j+1]) j = next[j];
if(chars[i] == chars[j+1]) j++;
next[i] = j;
}
if(next[len] > 0 && len % (len - next[len]) == 0){
return true;
}
return false;
}
}
232.用栈实现队列
算法链接:
类型: 栈和队列
难度: 简单
思路:
题解:
class MyQueue {
Stack<Integer> stackIn;
Stack<Integer> stackOut;
public MyQueue() {
stackIn = new Stack<>();
stackOut = new Stack<>();
}
public void push(int x) {
stackIn.push(x);
}
public int pop() {
dumpstackIn();
return stackOut.pop();
}
public int peek() {
dumpstackIn();
return stackOut.peek();
}
public boolean empty() {
return stackIn.isEmpty() && stackOut.isEmpty();
}
void dumpstackIn(){
if(!stackOut.isEmpty()) return;
while(!stackIn.isEmpty()){
stackOut.push(stackIn.pop());
}
}
}
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue obj = new MyQueue();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.peek();
* boolean param_4 = obj.empty();
*/
225. 用队列实现栈
算法链接:
类型: 栈和队列
难度: 简单
思路:
题解:
class MyStack {
Queue<Integer> q1 = new ArrayDeque<>();
Queue<Integer> q2 = new ArrayDeque<>();
public MyStack() {
}
public void push(int x) {
while(q1.size() > 0){
q2.add(q1.poll());
}
q1.add(x);
while(q2.size() > 0){
q1.add(q2.poll());
}
}
public int pop() {
return q1.poll();
}
public int top() {
return q1.peek();
}
public boolean empty() {
return q1.isEmpty();
}
}
/**
* Your MyStack object will be instantiated and called as such:
* MyStack obj = new MyStack();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.top();
* boolean param_4 = obj.empty();
*/
20. 有效的括号
算法链接:
类型: 栈和队列
难度: 简单
思路:用栈保存前括号,哈希表存储后括号信息,如果与栈顶括号匹配则出栈一个元素,最后判断栈是否为空。
题解:
class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
Map<Character,Character> map = new HashMap<>();
map.put('}','{');
map.put(')','(');
map.put(']','[');
for(int i = 0;i<s.length();i++){
if(s.charAt(i)=='}'||s.charAt(i)==')'||s.charAt(i)==']'){
if(!stack.isEmpty() && stack.peek()==map.get(s.charAt(i))){
stack.pop();
continue;
}
}
stack.push(s.charAt(i));
}
if(stack.isEmpty()){
return true;
}
return false;
}
}