【B站爱学习的饲养员】数据结构与算法-----刷Leetcode版【数据结构部分】

【常见时间复杂度】

        O(1),O(log N),O(N),O(Nlog N),O(N*N),O(M+N),

【常见空间复杂度】

        O(1),O(log N),O(N),O(Nlog N),O(N*N),O(M+N),

  1. 变量
  2. 递归(递归栈)

【数据结构】【数组】

定义及特点:

        在连续的内存空间中,存储一组相同类型的元素,索引从0开始,表示相对位置,

        适合读,不适合写===>读多写少

时间复杂度

访问(Access)

索引===>元素O(1)
搜索(Search)元素===>索引O(N)
插入(Insert)O(N)
删除(Delete)O(N)

【力扣485】

/**
 * @author 鼠鼠捏~~
 * @version 1.0~~
 * LeetCode 485 最大连续1的个数
 * 思路: 
 * 两个变量 :
 * count 用于存储中间结果
 * result 用于存储最后结果
 * 遍历数组,
 * 若该元素值为1,count++,
 * 否则 result = max(result,count),(当前结果与之前结果比较,最大值存入result),并清空count,重新开始记录1的个数
 * 遍历完成后返回max(result,count)(最后一次结果与之前结果比较)
 * 
 */
public class Exer1LC485 {
    public int Ex485(int[] arr){
        if (arr == null || arr.length == 0){
            return 0;
        }
        int count = 0;//中间值
        int result = 0;//结果值

        for(int i = 0;i < arr.length;i ++){
            if (arr[i] == 1){
                //出现 1 count++
                count++;
            }else {
                //出现 0 count与result比较 最大值存入result count清空
                result = count > result ? count:result;
                count = 0;

            }
        }
        result = count > result ? count:result;
        return  result;
    }
}

【数据结构】【链表】

【数据结构】【队列】

【数据结构】【栈】

定义及特点:

先进后出,浏览器后退功能

时间复杂度

访问(Access)

栈顶元素O(1)
搜索(Search)O(N)
插入(Insert)O(1)
删除(Delete)O(1)

【力扣20】

/**
 * @author 鼠鼠捏~~
 * @version 1.0~~
 * 要求:
 * 给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
 * <p>
 * 有效字符串需满足:
 * <p>
 * 左括号必须用相同类型的右括号闭合。
 * 左括号必须以正确的顺序闭合。
 * 每个右括号都有一个对应的相同类型的左括号。
 * <p>
 * 思路:
 * 遍历字符串s,
 * 若为左括号:直接入栈
 * 若为右括号:
 * 1.若此时栈空,return false
 * 2.栈非空,判断当前元素是否匹配栈顶元素,返回则出栈
 * 遍历结束后,判断栈是否为空,为空返回true;
 * isMatch函数用于判断是否匹配
 */
class Solution {
    public static boolean isValid(String s) {
        Stack<Object> stack = new Stack<>();
        //遍历字符串s
        for(int i = 0;i < s.length();i ++){
            char c = s.charAt(i);
            if (c =='('||c=='['||c=='{'  ){
                //c 为左括号,入栈
                stack.push(c);
            }else {
                //c 为右括号,判断栈是否为空
                if (stack.isEmpty()){
                    return false;
                }else {
                    if (isMatch((char)stack.peek(),c)){
                        if (!stack.isEmpty()){
                            stack.pop();
                        }
                    }else {
                        return false;
                    }
                }
            }
        }

        return stack.isEmpty();
    }
    public static boolean isMatch(char c1 ,char c2){
        if (c1 == '(' && c2 ==')'){
            return true;
        }else if (c1 == '[' && c2==']'){
            return true;
        }else if (c1 == '{' && c2 =='}'){
            return true;
        }else {
            return false;
        }


    }
}

【力扣496】

/**
 * @author 鼠鼠捏~~
 * @version 1.0~~
 * 要求:
 * nums1 中数字 x 的 下一个更大元素 是指 x 在 nums2 中对应位置 右侧 的 第一个 比 x 大的元素。
 * <p>
 * 给你两个 没有重复元素 的数组 nums1 和 nums2 ,下标从 0 开始计数,其中nums1 是 nums2 的子集。
 * <p>
 * 对于每个 0 <= i < nums1.length ,
 * 找出满足 nums1[i] == nums2[j] 的下标 j ,并且在 nums2 确定 nums2[j] 的 下一个更大元素 。
 * 如果不存在下一个更大元素,那么本次查询的答案是 -1 。
 * <p>
 * 返回一个长度为 nums1.length 的数组 ans 作为答案,满足 ans[i] 是如上所述的 下一个更大元素 。
 * 思路:
 * 两个栈stack temp
 * stack从上至下为倒序,temp从上至下为正序
 * nums2压入左栈stack
 * 对于int num = nums1[i],
 * 先遍历stack,压入右栈temp,直至找到num,此时判断temp.top 与 num的关系
 * top > num:nums1[i]==top,ttop压入左栈
 * top < num:ttop压入左栈,继续循环判断temp.top 与 num的关系,直至temp空
 * 结束后,若temp为空切nums[i]改变过,nums1[i]==-1,
 * 最后,temp全部元素压入左栈,恢复数据
 */
class Solution {
    public static int[] nextGreaterElement(int[] nums1, int[] nums2) {
        Stack<Integer> stack = new Stack<>();
        Stack<Integer> temp = new Stack<>();

        //nums2压入stack
        for (int i = 0; i < nums2.length; i++) {
            stack.push(nums2[i]);
        }

        for (int i = 0; i < nums1.length; i++) {
            int num=  nums1[i];
            //遍历stack,直至找到num,遍历元素压入temp
            while (!stack.isEmpty()) {
                if (stack.peek() != nums1[i]) {
                    temp.push(stack.pop());
                }else {
                    break;
                }
            }
            //判断temp.top num
            while (!temp.isEmpty()) {
                if (temp.peek() < nums1[i]) {
                    //ttop < num 压入stack
                    stack.push(temp.pop());
                } else if (temp.peek() > nums1[i]) {
                    //ttop > num 修改num
                    //同时ttop压入stack
                    nums1[i] = temp.peek();
                    stack.push(temp.pop());
                    break;
                }
            }
            if (temp.isEmpty() && num == nums1[i]) {
                //遍历temp 未找到,num = -1
                nums1[i] = -1;
            }
            while (!temp.isEmpty()) {
                stack.push(temp.pop());
            }
        }

        return nums1;
    }
}

/**
 * 思路二:
 * nums2存入stack不变
 *
 * 遍历stack,寻找nums1[i],并修改max
 * max存储nums1[i]右侧比nums1[i]大的数,每次>,均需修改max
 * isfound == false用于控制是否找到nums1[i]
 * stop<nums1[i],stop压入temp,
 * stop>nums1[i],max = stop,stop压入temp
 * stop=nums1[i],isfound = true,找到了,结束循环
 * nums1[i] = max
 * 恢复数据
 */
class Solution2 {
    public static int[] nextGreaterElement(int[] nums1, int[] nums2) {
        Stack<Integer> stack = new Stack<>();
        Stack<Integer> temp = new Stack<>();

        //nums2压入stack
        for (int i = 0; i < nums2.length; i++) {
            stack.push(nums2[i]);
        }
        for(int i = 0;i < nums1.length;i ++){
            int max = -1;//存储nums1[i]右侧比nums1[i]大的数,每次>,均需修改max
            boolean isFound = false;//标识是否找到nums1[i]

            while (!isFound){
                if (stack.peek() < nums1[i]){
                    //小于,stop压入temp,暂存
                    temp.push(stack.pop());
                }else if (stack.peek() > nums1[i]){
                    //大于,修改max,stop不知是否是右侧第一个压入temp,暂存
                    max = stack.peek();
                    temp.push(stack.pop());
                }else if (stack.peek() == nums1[i]){
                    isFound = true;
                }
            }

            //恢复数据
            while (!temp.isEmpty()){
                stack.push(temp.pop());
            }
            nums1[i] = max;
        }
        return nums1;
    }
}

【数据结构】【哈希表】

定义及特点:

       又称散列表,以键值对形式存放数据

时间复杂度

访问(Access)

搜索(Search),考虑碰撞O(1)
插入(Insert),考虑碰撞      O(1)
删除(Delete),考虑碰撞O(1)
碰撞O  (K)
public class CommonOperate {
    public static void main(String[] args) {
        //创建哈希表
        //1.数组创建哈希表,数组元素的索引作为key,数组元素的值作为value
        String [] hashTable = new String[4];
        //2.Java自带创建哈希表
        HashMap<Integer, String> map = new HashMap<>();

        //添加元素,O(1)
        hashTable[1] = "韩梅梅";
        hashTable[2] = "李华";
            
        map.put(1,"韩梅梅");
        map.put(2,"李华");
        
        //更新元素,O(1)
        hashTable[1]=  "bishi";
        
        map.put(1,"bishi");//多次put,直接覆盖

        //删除元素,O(1)
        hashTable[1] = " ";
        
        map.remove(1);
        

        //获取key的值,O(1)
        String temp = hashTable[3];
        
        map.get(3);

        //检查key是否存在,O(1)
        map.containsKey(4);
        
        //哈希表长度,O(1)
        map.size();
        
        //哈希表是否为空,O(1)
        map.isEmpty();
    }
}

【LC217】

/**
 * LC217:
 *
 * 要求:
 * 给你一个整数数组 nums 。
 * 如果任一值在数组中出现 至少两次 ,返回 true ;
 * 如果数组中每个元素互不相同,返回 false 。
 *
 * 思路:
 * nums存入哈希表,检查前后长度是否一致
 */

class Solution {
    public static boolean containsDuplicate(int[] nums) {

        HashMap<Integer, Integer> hashMap = new HashMap<>();

        for(int i = 0;i < nums.length;i ++){
            hashMap.put(nums[i],nums[i]);
        }
        System.out.println(hashMap.toString());

        return !(hashMap.size()== nums.length);
    }
}

【LC705】

/**
 * LC 705 设计一个哈希集合
 *
 * 要求:
 * 不使用任何内建的哈希表库设计一个哈希集合(HashSet)。
 *
 * 实现 MyHashSet 类:
 *
 * void add(key) 向哈希集合中插入值 key 。
 * bool contains(key) 返回哈希集合中是否存在这个值 key 。
 * void remove(key) 将给定值 key 从哈希集合中删除。如果哈希集合中没有这个值,什么也不做。
 * 0 <= key <= 10^6
 * 最多调用 10^4 次 add、remove 和 contains
 *
 *
 * 思路:
 * 创建一个大小为10^6的boolean数组
 * true false代表哈希集合中是否有该key
 */
class MyHashSet {
    boolean[] hashSet = new boolean[1000001];

    public MyHashSet() {

    }

    public void add(int key) {
        hashSet[key] = true;
    }

    public void remove(int key) {
        hashSet[key] = false;
    }

    public boolean contains(int key) {
            return hashSet[key];
    }
}

【数据结构】【树】

定义及特点:

        “父子关系”,包含根节点,叶子节点,计算高度,从0开始,由下到上,计算深度,从0开始,由上到下,计算层数,从1开始,由上到下

二叉树

分类

  • 普通二叉树:每个节点最多两个“孩子”
  • 满二叉树:除叶子节点外,每个节点都有两个“孩子”,所有叶子节点在同一层
  • 完全二叉树:从树的根节点,从上到下,从左到右,依次填满节点

满二叉树不等同于完全二叉树,满二叉树是完全二叉树,反之不成立

遍历

  • 前序遍历:根节点==>左子树==>右子树
  • 中序遍历:左子树==>根节点==>右子树
  • 后序遍历:左子树==>右子树==>根节点

【LC144】

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        preorder(root, res);
        return res;
    }

    public void preorder(TreeNode root, List<Integer> res) {
        if (root == null) {
            return;
        }
        res.add(root.val);
        preorder(root.left, res);
        preorder(root.right, res);
    }


}

【LC94】

/**
 * LC 144 二叉树的中序遍历
 * 前序遍历:左子树 ==> 根节点 == >右子树
 * <p>
 * 要求:
 * 给你二叉树的根节点 root ,返回它节点值的 中序 遍历。
 * <p>
 * 思路:
 *
 */

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        inorder(root, res);
        return res;
    }

    public void inorder(TreeNode root, List<Integer> res) {
        if (root == null) {
            return;
        }

        inorder(root.left, res);

        res.add(root.val);

        inorder(root.right, res);
    }
}

【LC145】

/**
 * LC 144 二叉树的后序遍历
 * 前序遍历:左子树 ==> 右子树 == >根节点
 * <p>
 * 要求:
 * 给你二叉树的根节点 root ,返回它节点值的 后序 遍历。
 * <p>
 * 思路:
 *
 */
class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        postorder(root, res);
        return res;
    }

    public void postorder(TreeNode root, List<Integer> res) {
        if (root == null) {
            return;
        }

        postorder(root.left, res);
        postorder(root.right, res);
        res.add(root.val);


    }
}

【数据结构】【堆】

定义及特点:

        完全二叉树,堆中每一个节点的值均 大于等于其孩子节点(最大堆)或小于等于其孩子节点(最小堆)

     

时间复杂度

访问(Access)

搜索(Search)O(1),堆顶元素        
插入(Insert)      O(log N)
删除(Delete)O(log N),堆顶元素

【数据结构】【图】

定义及特点:

        “朋友关系”,顶点,“邻居节点”,边,度,

        分类:有向图,无向图,权重图

        入度:多少边指向该顶点

        出度:多少边以这个点为起点指向别的顶点

        权重图求最短路径:

  • 贝尔曼-福特算
  • 迪克斯特拉算法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值