算法学习记录

目录


字符串

  1. 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;
            }
        }
    }

 459. 重复的子字符串 - 力扣(LeetCode)

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、用双栈实现队列

232. 用栈实现队列 - 力扣(LeetCode)

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();
    }
}

使用两个队列实现栈的功能:

  20. 有效的括号 - 力扣(LeetCode)

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;
    }
}

150. 逆波兰表达式求值 - 力扣(LeetCode)

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();
    }
}

239. 滑动窗口最大值 - 力扣(LeetCode)

实现一个单调栈

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;
    }
}

347. 前 K 个高频元素 - 力扣(LeetCode)

优先队列的使用

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--;
            }
        }
    }
}

144. 二叉树的前序遍历 - 力扣(LeetCode)

采用递归法

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);
        }
    }
}

226. 翻转二叉树 - 力扣(LeetCode)

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;
    }
}

101. 对称二叉树 - 力扣(LeetCode)

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;
    }
}

257. 二叉树的所有路径 - 力扣(LeetCode)

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;
    }
}


动态规划

377. 组合总和 Ⅳ - 力扣(LeetCode)

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];
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值