目录
字符串
- kmp算法
字符串匹配 - KMP 算法原理和实现 | 春水煎茶 - 王超的个人博客 (writings.sh)28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)class Solution { public int strStr(String haystack, String needle) { //kmp算法 if (needle.length()==0) return -1; 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; } public void getNext(int[] next,String needle) //mp算法 得到前缀表 { int j = 0; next[0] = 0; for(int i = 1;i<needle.length();i++) { while (j>0&&needle.charAt(i)!=needle.charAt(j)) //不相等时回溯 j = next[j-1]; if(needle.charAt(j)==needle.charAt(i)) j++; next[i] = j; } } }
class Solution {
public boolean repeatedSubstringPattern(String s) { //mp算法求子串
int[] next = new int[s.length()];
int j = 0;
next[0] = 0;
for(int i = 1;i<s.length();i++)
{
while(j>0&&s.charAt(i)!=s.charAt(j))
j = next[j-1];
if(s.charAt(j)==s.charAt(i))
j++;
next[i] = j;
}
int num = next[s.length()-1];
if(num%(s.length()-num)==0&&num>0) return true;
return false;
}
}
栈和队列
1、用双栈实现队列
import java.util.Stack;
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() {
while (!stackOut.empty()) return stackOut.pop();
while (!stackIn.empty()){
stackOut.push(stackIn.pop());
}
return stackOut.pop();
}
public int peek() {
while (!stackOut.empty()) return stackOut.peek();
while (!stackIn.empty()){
stackOut.push(stackIn.pop());
}
return stackOut.peek();
}
public boolean empty() {
if(stackIn.empty()&&stackOut.empty()) return true;
return false;
}
}
/**
* 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();
*/
2、用队列实现栈
225. 用队列实现栈 - 力扣(LeetCode)使用一个队列实现栈的功能:
import java.util.LinkedList;
import java.util.Queue;
/*
queue.offer() add()添加失败(队列已满)时会报运行时异常 offer()只会返回false
queue.add() 均为插入在尾部添加元素,禁止添加null 元素,会报空指针
remove() 均为删除并返回头部元素,队列为空时 poll()返回null
poll() remove() 会报错( NoSuchElementException )
peek() 获取 返回null
element() 抛异常
*/
class MyStack {
Queue<Integer> queue;
int counter;
boolean istop = false;
public MyStack() {
queue = new LinkedList<>(); //使用链表创造队列
}
public void push(int x) {
queue.offer(x);
istop = false;
}
public int pop() {
if(istop){
istop = false;
return queue.poll();
}
counter = queue.size();
while (counter!=1)
{
queue.offer(queue.poll());
counter--;
}
return queue.poll();
}
public int top() {
if(istop) return queue.peek();
counter = queue.size();
while(counter!=1)
{
queue.offer(queue.poll());
counter--;
istop = true;
}
return queue.peek();
}
public boolean empty() {
return queue.isEmpty();
}
}
使用两个队列实现栈的功能:
import java.util.Stack;
class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
for(int i = 0;i < s.length();i++)
{
if(s.charAt(i)=='('||s.charAt(i)=='['||s.charAt(i)=='{')
{
stack.push(s.charAt(i));
}else{
if(stack.empty()) return false;
else if(s.charAt(i)==')'&&stack.pop()!='(') return false;
else if(s.charAt(i)==']'&&stack.pop()!='[') return false;
else if(s.charAt(i)=='}'&&stack.pop()!='{') return false;
}
}
return true;
}
}
1047. 删除字符串中的所有相邻重复项 - 力扣(LeetCode)
import java.util.Stack;
class Solution {
public String removeDuplicates(String s) {
Stack<Character> stack = new Stack<>();
for(int i = 0;i < s.length();i++)
{
if(!stack.isEmpty()&&stack.peek()==s.charAt(i)){
stack.pop();
}
else{
stack.push(s.charAt(i));
}
}
String result = "";
while(!stack.isEmpty())
result = stack.pop() + result; //字符串反转的一种方式
return result;
}
}
import java.util.Stack;
class Solution {
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<>();
for(String s : tokens)
{
if(s.equals("+"))
{
stack.push(stack.pop()+stack.pop());
}else if(s.equals("-")){
stack.push(-stack.pop()+stack.pop());
}else if(s.equals("*"))
{
stack.push(stack.pop()*stack.pop());
}else if(s.equals("/")){
int a = stack.pop();
int b = stack.pop();
stack.push(b/a);
}else{
stack.push(Integer.parseInt(s));
}
}
return stack.pop();
}
}
实现一个单调栈
import java.util.ArrayDeque;
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
ArrayDeque<Integer> deque = new ArrayDeque<>();
int[] res = new int[nums.length - k+1];
for(int i = 0;i<nums.length;i++) //这个单调队列需要根据下标来判断第一个是不是应该出队
{
while(!deque.isEmpty()&&deque.peek()<=i-k)
{
deque.poll();
}
while (!deque.isEmpty()&&nums[deque.peekLast()]<nums[i]){
deque.pollLast();
}
deque.offer(i);
if(i>=k-1)
{
res[i-k+1] = nums[deque.peek()];
}
}
return res;
}
}
优先队列的使用
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer,Integer> map = new HashMap<>();
for(int num:nums)
{
map.put(num,map.getOrDefault(num,0)+1); //map.getOrDefault当Map集合中有这个key时,就使用这个key值;如果没有就使用默认值defaultValue。
}
PriorityQueue<int[]> pq = new PriorityQueue<>((pair1,pair2)->pair1[1]-pair2[1]);
for(Map.Entry<Integer,Integer> entry:map.entrySet()){ //map.entrySet 直接取得key和value的值的集合
if(pq.size()<k){
pq.add(new int[]{entry.getKey(),entry.getValue()});
}else{
if(entry.getValue()>pq.peek()[1]){
pq.poll();
pq.add(new int[]{entry.getKey(),entry.getValue()});
}
}
}
int[] ans = new int[k];
for(int i =k-1;i>-1;i--)
{
ans[i] = pq.poll()[0];
}
return ans;
}
}
树
树的遍历(前序)
//-------------------------------------------------------------------------
class Traverse{
public void preorder_recursive(TreeNode node){ //递归法的前序遍历
if(node==null) return;
System.out.println(node.data);
if(node.left!=null) preorder_recursive(node.left);
if(node.right!=null) preorder_recursive(node.right);
}
//------------------------------------------------------------------------
public void preorder_Iterative(TreeNode node){ //迭代法的前序遍历
Stack<TreeNode> stack = new Stack<>();
if(node!=null) stack.push(node);
while(!stack.isEmpty()){
TreeNode tmp = stack.pop();
if(node!=null) {
stack.push(tmp);
stack.push(null);
stack.push(tmp.right);
stack.push(tmp.left);
}else{
node = stack.pop();
System.out.println(node.data;
}
}
}
//-----------------------------------------------------------------------
public void levelOrder_Iterative(TreeNode node){
Queue<TreeNode> que = new LinkedList<>();
if(node!=null) que.offer(node);
while(!que.isEmpty()){
int len = que.size();
while(len>0){
TreeNode tmp = que.poll();
System.out.println(tmp.data);
if(tmp.right!=null) que.offer(tmp.right);
if(tmp.left!=null) que.offer(tmp.left);
len--;
}
}
}
}
采用递归法
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
preorder(root,result);
return result;
}
public void preorder(TreeNode root,List<Integer> result)
{
if(root == null)
return;
result.add(root.val);
preorder(root.left,result);
preorder(root.right,result);
}
}
采用迭代法
//----------------------前序遍历
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if(root == null) return result;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while(!stack.isEmpty()){
TreeNode node = stack.pop();
result.add(node.val);
if(node.right!=null) stack.push(node.right);
if(node.left!=null) stack.push(node.left);
}
return result;
}
}
//---------------------------中序遍历
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if(root == null) return result;
Stack<TreeNode> stack = new Stack<>();
TreeNode node = root;
while(node!=null||!stack.isEmpty()){
if(node!=null){
stack.push(node);
node = node.left;
}else{
node = stack.pop();
result.add(node.val);
node = node.right;
}
}
return result;
}
}
树迭代法遍历的统一写法(举后序遍历为例子)
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
if(root!=null) stack.push(root);
while(!stack.isEmpty()){
TreeNode node = stack.pop();
if(node!=null){
stack.push(node);
stack.push(null);
if(node.right!=null) stack.push(node.right);
if(node.left!=null) stack.push(node.left);
}else{
node = stack.pop();
result.add(node.val);
}
}
return result;
}
}
宽度搜索模板
class Solution { //--------------递归法
public List<List<Integer>> resList = new ArrayList<>();
public List<List<Integer>> levelOrder(TreeNode root) {
checkFun1(root,0);
return resList;
}
public void checkFun1(TreeNode root,int deep)
{
if(root==null) return;
deep++;
if(resList.size()<deep){
List<Integer> item = new ArrayList<>();
resList.add(item);
}
resList.get(deep-1).add(root.val);
checkFun1(root.left,deep);
checkFun1(root.right,deep);
}
}
//bfs的递归法当需要记录每一层的节点个数时通常需要一个辅助数组
class Solution { //借助队列
public List<List<Integer>> resList = new ArrayList<>();
public List<List<Integer>> levelOrderBottom(TreeNode root) {
checkFun(root);
return resList;
}
public void checkFun(TreeNode node){
if(node==null) return;
Queue<TreeNode> que = new LinkedList<>();
que.offer(node);
while(!que.isEmpty()){
int len = que.size(); //借助队列时len就是每一层的节点个数!!
List<Integer> listItem = new ArrayList<>();
while(len>0)
{
TreeNode tmpNode = que.poll();
listItem.add(tmpNode.val);
if(tmpNode.left!=null) que.offer(tmpNode.left);
if(tmpNode.right!=null) que.offer(tmpNode.right);
len--;
}
resList.add(listItem);
}
}
}
class Solution { //层序遍历反转二叉树
public TreeNode invertTree(TreeNode root) {
Queue<TreeNode> que = new LinkedList<>();
if(root!=null) que.offer(root);
while(!que.isEmpty())
{
int len = que.size();
for(int i = 0;i<len;i++)
{
TreeNode temp = que.poll();
if(temp.left!=null) que.offer(temp.left);
if(temp.right!=null) que.offer(temp.right);
TreeNode tmp = temp.left;
temp.left = temp.right;
temp.right = tmp;
}
}
return root;
}
}
//---------------------------------------------深度搜索递归法
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root==null) return null;
invertTree(root.left);
invertTree(root.right);
swap(root);
return root;
}
public void swap(TreeNode a){
TreeNode tmp = a.left;
a.left = a.right;
a.right = tmp;
}
}
//----------------------------------------------深度搜索迭代法
class Solution {
public TreeNode invertTree(TreeNode root) {
Stack<TreeNode> stack = new Stack();
if(root!=null) stack.push(root);
while(!stack.isEmpty())
{
TreeNode node = stack.pop();
if (node != null) {
if(node.right!=null) stack.push(node.right);
if(node.left!=null) stack.push(node.left);
stack.push(node);
stack.push(null);
}else{
node = stack.pop();
TreeNode tmp = node.left;
node.left = node.right;
node.right = tmp;
}
}
return root;
}
}
class Solution { //采用层序遍历来判断是否镜像
public boolean isSymmetric(TreeNode root) {
Queue<TreeNode> que = new LinkedList<>();
que.offer(root.left);
que.offer(root.right);
while(!que.isEmpty()){
TreeNode leftNode = que.poll();
TreeNode rightNode = que.poll();
if(leftNode==null&&rightNode==null){
continue;
}
if(leftNode==null||rightNode==null||leftNode.val!=rightNode.val){
return false;
}
que.offer(leftNode.left);
que.offer(rightNode.right);
que.offer(leftNode.right);
que.offer(rightNode.left);
}
return true;
}
}
//采用的递归法判断是否镜像
class Solution {
public boolean isSymmetric(TreeNode root) {
if(root==null) return true;
return compare(root.left,root.right);
}
public boolean compare(TreeNode left,TreeNode right){
if(left==null&&right==null) return true;
if(left==null||right==null||left.val!=right.val){
return false;
}
boolean compareOutside = compare(left.left,right.right);
boolean compareInside = compare(left.right,right.left);
return compareOutside&&compareInside;
}
}
class Solution {
public List<String> binaryTreePaths(TreeNode root) {
List<Integer> paths = new ArrayList<>();
List<String> res = new ArrayList<>();
if(root == null) return res;
traversal(root,paths,res);
return res;
}
//-----------------------------------------运用回溯的方式
public void traversal(TreeNode node,List<Integer> paths,List<String> res){
paths.add(node.val);
if(node.right==null&&node.left==null){
StringBuffer buffer = new StringBuffer();
for(int i = 0;i<paths.size()-1;i++){
buffer.append(paths.get(i)+"->");
}
buffer.append(paths.get(paths.size()-1));
res.add(buffer.toString());
}
if(node.left!=null){
traversal(node.left,paths,res);
paths.remove(paths.size()-1);
}
if(node.right!=null){
traversal(node.right,paths,res);
paths.remove(paths.size()-1);
}
}
}
本题采用的迭代法,有些繁琐了
class Solution {
Stack<TreeNode> stack = new Stack<>();
public boolean isSubtree(TreeNode root, TreeNode subRoot) {
if(root==null&&subRoot==null) return true;
if(root==null||subRoot==null) return false;
stack.push(root);
while(true){
TreeNode same = sameRoot(subRoot);
if(same==null) return false;
else if(sameTree(same,subRoot)) return true;
}
}
public TreeNode sameRoot(TreeNode subRoot){
while(!stack.isEmpty()){
TreeNode tmp = stack.pop();
if(tmp!=null){
stack.push(tmp);
stack.push(null);
if(tmp.right!=null) stack.push(tmp.right);
if(tmp.left!=null) stack.push(tmp.left);
}else{
tmp = stack.pop();
if(tmp.val==subRoot.val) return tmp;
}
}
return null;
}
public boolean sameTree(TreeNode root,TreeNode subRoot){
if(root==null&&subRoot==null) return true;
if(root==null||subRoot==null||root.val!=subRoot.val) return false;
boolean left = sameTree(root.left,subRoot.left);
boolean right = sameTree(root.right,subRoot.right);
return left && right;
}
}
//------------------------------验证二叉搜索树的方式
//---------------------------去查看他的中序是否为递增的次序
class Solution {
TreeNode max;
public boolean isValidBST(TreeNode root) {
if(root==null) return true;
boolean left = isValidBST(root.left);
if(!left) return false;
if(max!=null&&root.val<=max.val) return false;
max = root;
boolean right = isValidBST(root.right);
return right;
}
}
动态规划
class Solution {
public int combinationSum4(int[] nums, int target) {
int[] dp = new int[target+1];
dp[0] = 1;
//物品数在内,容量大小在外时为排列
for(int i = 0;i<=target;i++){
for(int j = 0;j<nums.length;j++){
if(i>=nums[j])
dp[i] += dp[i-nums[j]];
}
}
return dp[target];
}
}
class Solution {
public int change(int amount, int[] coins) {
int[] dp = new int[amount+1];
dp[0] = 1;
//容量在内,物品数在外 为组合
for(int i = 0;i<coins.length;i++)
{
for(int j = coins[i];j<dp.length;j++)
{
dp[j] += dp[j-coins[i]];
}
}
return dp[amount];
}
}