当前位置: 首页 > news >正文

记录:2022-9-30 打家劫舍 二叉搜索树中第K小的元素 公平锁 磁盘调度

学习时间:2022-9-30

学习内容

1、LeetCode

198. 打家劫舍

在这里插入图片描述

思路

dp[i] = dp[i-1]之前的最大值 + num[i]
优化思路:把最大值用一个变量来存

代码

class Solution {
    public int rob(int[] nums) {
        int[] dp = new int[nums.length];
        if(nums.length == 1){
            return nums[0];
        }
        if(nums.length == 2){
            return Math.max(nums[0],nums[1]);
        }
        int max = nums[0];
        dp[0] = nums[0];
        dp[1] = nums[1];
        int ans = Math.max(dp[0],dp[1]);
        for(int i = 2;i<nums.length;i++){
            dp[i] = nums[i] + max;
            max = Math.max(max,dp[i-1]);
            ans = Math.max(dp[i],ans);
        }
        return ans;
    }
}

在这里插入图片描述

更优解

优化DP数组为一个变量

public int rob(int[] nums) {
    int prev = 0;
    int curr = 0;

    // 每次循环,计算“偷到当前房子为止的最大金额”
    for (int i : nums) {
        // 循环开始时,curr 表示 dp[k-1],prev 表示 dp[k-2]
        // dp[k] = max{ dp[k-1], dp[k-2] + i }
        int temp = Math.max(curr, prev + i);
        prev = curr;
        curr = temp;
        // 循环结束时,curr 表示 dp[k],prev 表示 dp[k-1]
    }

    return curr;
}

作者:nettee
链接:https://leetcode.cn/problems/house-robber/solution/dong-tai-gui-hua-jie-ti-si-bu-zou-xiang-jie-cjavap/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

230. 二叉搜索树中第K小的元素

在这里插入图片描述

思路

要注意他是二叉搜索树,如果要找的话,可以从最小开始,然后用一个栈来不停的push和pop,具体为让节点所有左孩子进栈,每次出栈时让该元素的右节点进栈,然后将右节点的所有左孩子也进栈,循环此过程

代码

class Solution {
    Stack<TreeNode> path = new Stack<TreeNode>();
    int ans;
    int index = 0;
    public int kthSmallest(TreeNode root, int k) {
        TreeNode temp = root;
        while(temp!=null){
            path.push(temp);//所有左节点进栈
            ans = temp.val;
            temp = temp.left;
        }
        while(!path.isEmpty()){
            TreeNode node = path.pop();
            index++;
            if(k == index){
                ans = node.val;
                break;
            }
            if(node.right!=null){
                //将right所有左子树进栈
                TreeNode right = node.right;
                while(right != null){
                    path.push(right);//所有左节点进栈
                    right = right.left;
                }
            }
        }
        return ans;
    }
}

在这里插入图片描述

更优解

记录子树的结点数

class Solution {
    public int kthSmallest(TreeNode root, int k) {
        MyBst bst = new MyBst(root);
        return bst.kthSmallest(k);
    }
}

class MyBst {
    TreeNode root;
    Map<TreeNode, Integer> nodeNum;

    public MyBst(TreeNode root) {
        this.root = root;
        this.nodeNum = new HashMap<TreeNode, Integer>();
        countNodeNum(root);
    }

    // 返回二叉搜索树中第k小的元素
    public int kthSmallest(int k) {
        TreeNode node = root;
        while (node != null) {
            int left = getNodeNum(node.left);
            if (left < k - 1) {
                node = node.right;
                k -= left + 1;
            } else if (left == k - 1) {
                break;
            } else {
                node = node.left;
            }
        }
        return node.val;
    }

    // 统计以node为根结点的子树的结点数
    private int countNodeNum(TreeNode node) {
        if (node == null) {
            return 0;
        }
        nodeNum.put(node, 1 + countNodeNum(node.left) + countNodeNum(node.right));
        return nodeNum.get(node);
    }

    // 获取以node为根结点的子树的结点数
    private int getNodeNum(TreeNode node) {
        return nodeNum.getOrDefault(node, 0);
    }
}

作者:LeetCode-Solution
链接:https://leetcode.cn/problems/kth-smallest-element-in-a-bst/solution/er-cha-sou-suo-shu-zhong-di-kxiao-de-yua-8o07/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

在这里插入图片描述
效率比我的还低。。当令解算了

2、Java锁机制(3) 公平锁

ReentrantLock

公平锁和非公平锁的实现是ReentrantLock
当调用公平锁时,调用此方法

static final class FairSync extends Sync {
        final void lock() {
            acquire(1);
        }
}
    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

这里需要分析tryAcquire和acquireQueued方法

        protected final boolean tryAcquire(int acquires) {//1
            final Thread current = Thread.currentThread();
            int c = getState();//c==0 则说明有可能可以执行,因为公平锁还需要排队
            if (c == 0) {//如果此时
                if (!hasQueuedPredecessors() &&//如果前面还有元素,则无法加锁,返回false
                    compareAndSetState(0, acquires)) {//这个考虑的是并发原子性问题,如果被其他线程先抢占,则等待
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {//可重入锁 一个线程可以多次加锁
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

对于上述的hasQueuedPredecessors方法,实际上是使用了AQS队列,
队列是一个双向链表,一个node上有thread,还有一个waitStatus,这个属性会被他的下一个节点赋值成-1,代表这个node后面还有元素,需要唤醒

    public final boolean hasQueuedPredecessors() {
        Node t = tail; // Read fields in reverse initialization order
        Node h = head;
        Node s;
        return h != t &&//还有元素
            ((s = h.next) == null //并发问题,如果有第三个节点进来,发现s==null,说明第二个节点正在操作,第三个节点返回true,表示前面还有排队的元素
            || s.thread != Thread.currentThread());//如果不是当前的线程,则说明还没执行到他,前面就还存在元素
    }
//这个代码会将node加入到队列中挂起,上面的两个方法作用为:先尝试获取锁,如果获取不到锁,则尝试将node加入到队列中。完成这个操作后中断当前线程
    final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();//循环获取node的上一个元素
                if (p == head && tryAcquire(arg)) {//如果上一个元素是head,说明p是第一个应该出队的元素,然后去加锁,如果加锁成功,执行以下方法
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&//加锁失败的代码,如果这里还失败,将会继续请求,外层是一个循环
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

3、磁盘调度

磁盘调度问题是一个多线程问题,有多个线程需要请求数据,有一个线程来负责寻道

FCFS调度

先来先服务,从队列中pop出元素并移动磁盘

SSTF 最短寻道距离

每次找离目前最近的距离
这可能会引发饥饿

SCAN算法(电梯算法)

先从一个方向开始,每次找离的最近的,然后再反向移动

LOOK算法

在SCAN基础上,当移动到最后,会回到开始的位置,形成一个环形队列

相关文章:

  • 基于html宠物用品商城项目的设计与实现(学生网页设计作业源码)
  • 【Java复习】线程安全的 HashMap --- ConcurrentHashMap
  • 《文化相对论》:危机重重的世界,对话才能产生转机
  • 水溶性CuInS/ZnS 量子点 PL 550 nm--800 nm
  • Vue3和react状态管理之Redux与Pinia的使用比较
  • 新学期如何克服“社恐”,猿辅导老师给高中生三条建议
  • 浅析各种主流区块链共识算法的利与弊
  • [架构之路-16]:目标系统 - 硬件平台 - CPU主要物理性能指标
  • 【JAVASE】JDK8新特性
  • 【0121】建立与postgres后端的连接(2)
  • 交换机、IP地址、ARP协议
  • 迭代器并不全是指针,list的迭代器与vector和string的有什么不一样,让博主告诉你其底层原理!
  • 80页4万字政务综合服务平台建设项目方案书(完整版)
  • Python03--python中的标识符和变量以及数据类型
  • 微信小程序开发实战(API及多人协调开发)
  • ABAP的include关键字,Java的import, C的include和C4C ABSL 的import比较
  • es6(二):字符串的扩展
  • MySQL几个简单SQL的优化
  • October CMS - 快速入门 9 Images And Galleries
  • Puppeteer:浏览器控制器
  • SAP云平台运行环境Cloud Foundry和Neo的区别
  • UEditor初始化失败(实例已存在,但视图未渲染出来,单页化)
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • VuePress 静态网站生成
  • 初探 Vue 生命周期和钩子函数
  • 回顾 Swift 多平台移植进度 #2
  • 计算机常识 - 收藏集 - 掘金
  • 聊聊sentinel的DegradeSlot
  • 目录与文件属性:编写ls
  • 深度学习中的信息论知识详解
  • 一道闭包题引发的思考
  • 由插件封装引出的一丢丢思考
  • 微龛半导体获数千万Pre-A轮融资,投资方为国中创投 ...
  • ​LeetCode解法汇总2808. 使循环数组所有元素相等的最少秒数
  • !!java web学习笔记(一到五)
  • # 日期待t_最值得等的SUV奥迪Q9:空间比MPV还大,或搭4.0T,香
  • #基础#使用Jupyter进行Notebook的转换 .ipynb文件导出为.md文件
  • (2022 CVPR) Unbiased Teacher v2
  • (PHP)设置修改 Apache 文件根目录 (Document Root)(转帖)
  • (安全基本功)磁盘MBR,分区表,活动分区,引导扇区。。。详解与区别
  • (超详细)语音信号处理之特征提取
  • (附源码)ssm失物招领系统 毕业设计 182317
  • (个人笔记质量不佳)SQL 左连接、右连接、内连接的区别
  • (一)Thymeleaf用法——Thymeleaf简介
  • (原)Matlab的svmtrain和svmclassify
  • (转载)PyTorch代码规范最佳实践和样式指南
  • (转载)利用webkit抓取动态网页和链接
  • .java 9 找不到符号_java找不到符号
  • .jks文件(JAVA KeyStore)
  • .net Application的目录
  • .NET C# 使用 SetWindowsHookEx 监听鼠标或键盘消息以及此方法的坑
  • .NET Standard / dotnet-core / net472 —— .NET 究竟应该如何大小写?
  • .Net Web项目创建比较不错的参考文章
  • .net 程序发生了一个不可捕获的异常
  • .NET的数据绑定