yubのAlgorithm.0x9
两数之和link:1. 两数之和 - 力扣(LeetCode)
思路分析看到题目描述首先想到用两层for循环解决问题.分别从i位置和j(i+1)位置开始相加遍历判断.注意不越界条件
数组1234567891011121314151617181920212223242526class Solution { public int[] twoSum(int[] nums, int target) { //我们要找到2个数之和等于target //即我们需要找到nums[i] + nums[j] == target,并且返回他们的下标(i和j),其中i != j int[] ans = new int[2]; //声明一个大小为2的数组用来保存结果 //我们通过循环来遍历所有的数字 int n = nums.length; //用一个变量n保存nums的长度 //i为第一个数的下标,nums一共有n个数,所以i的取值范围是[0, n-1] for(int i = 0; ...
yubのAlgorithm.0xc
反转字符串IIlink:541. 反转字符串 II - 力扣(LeetCode)
思路分析关键点在于我们要找对反转思路,2k是一个区间,没达到条件和达到条件之后怎么处理.因此考虑怎么筛选条件.
首先创建一个字符数组用于存储遍历的下标位置用于筛选【其实类似双指针判断 此时尾指针的判断 避免越界】判断区间为[数组长度-1,起始位置 + k - 1]
12345678910111213141516171819class Solution { public String reverseStr(String s, int k) { char[] ch = s.toCharArray(); for(int i = 0;i < ch.length;i += 2*k) { int start = i; //防止越界 平移判断区间和length比较 int end = Math.min(ch.length -1 ,start + k - 1); ...
yubのAlgorithm.0xa
赎金信link:383. 赎金信 - 力扣(LeetCode)
思路分析关键分析觉得是次数统计,ransomNote中的字符出现次数和magazine中统计次数相同即可.(有点相同字母异序词的味->哈希数组实现【大小写转换】)题目又说是两个字符串全为小写字母,有数量限制(少量).方便进行映射.可以暴力两层for循环求解,但又想到先前接触的哈希map进行映射.
Tip本题目使用map消耗的空间资源比数组大一些.map要维护红黑树或哈希表还要做哈希函数,更费时.【数据量大时更能体现】
数组1234567891011121314151617181920212223class Solution { public boolean canConstruct(String ransomNote, String magazine) { //创建需要的数组和中间汴梁 int[] arr = new int[26]; int tmp = 0; //遍历rans 在magazine中映射确定 下标位置标记逐增 ...
yubのAlgorithm.0xd
用栈实现队列link:232. 用栈实现队列 - 力扣(LeetCode)
思路分析首先理清楚栈和队列的异同.队列是先进先出 栈先进后出【两者都能存储元素】再来看peek()和poll().栈和队列都有peek() 可以称之为“瞄一眼”只是看一下当前栈顶/队头元素是什么.栈中的pop()直接返回栈顶元素(出栈)队列中的poll()在某种层面上就等效于pop()了.
先用栈1存储所有元素 再逐个pop到栈2中最后pop栈2全部元素.注意判断栈满(是否需要扩容)
12345678910111213141516171819202122232425262728293031323334353637383940414243444546class MyQueue { private Stack<Integer> stack1; private Stack<Integer> stack2; public MyQueue() { stack1 = new Stack<>(); stack2 = new ...
yubのAlgorithm.0xb
反转字符串link:344. 反转字符串 - 力扣(LeetCode)
思路分析其实最开始学C语言的时候,也遇到过类似题目.当时自以为的投机取巧无非只是倒序打印而不是逆置元素.(hh 果然小白都会这样 当然也有更聪明的小懒狗直接用库函数 【及其不推荐】
双指针1234567891011121314class Solution { public void reverseString(char[] s) { int left = 0; int right = s.length - 1; while(left < right) { char tmp = s[left]; s[left] = s[right]; s[right] = tmp; right--; left++; } }}
Tip
更优雅的处理方式——异或因为a ^ a = 0,b ...
yubのAlgorithm.0xe
逆波兰表达式求值link:150. 逆波兰表达式求值 - 力扣(LeetCode)
思路分析最开始的思路就是用栈解决,非运算符号的先入栈,遇到运算符再出栈对运算符进行判断之后进行相应的运算最后出栈即可.【注意一点】 为了保证运算顺序,运算都是num2对num1操作(因为先进后出)
前提是搞懂逆波兰式本质是二叉树中的中序遍历变成了后序遍历.
暴力版12345678910111213141516171819202122232425262728293031323334class Solution { public int evalRPN(String[] tokens) { Stack<Integer> stack = new Stack<>(); int num1,num2; for(String s:tokens) { if(s.equals("+")) { stack.p ...
yubのAlgorithm.0xf
前K个高频元素link:347. 前 K 个高频元素 - 力扣(LeetCode)
思路分析对于统计元素出现的频率,这一类问题可以用map来进行统计(key和value无敌)key存放元素,value存放出现的频率.其实最开始想到的是暴力的遍历循环,逐个判断计数排列,剔除出现频率最小的元素.想用set但是不匹配统计频率的要求.就需要Set和Lsit结合.最后发现还是离不开心爱的map啊(大顶堆秒了)
大顶堆实现1234567891011121314151617181920class Solution { public int[] topKFrequent(int[] nums, int k) { //创建Map Map<Integer,Integer> map = new HashMap<>(); for(int num:nums) { //确保更新元素 map.put(num,map.getOrDefault(num,0)+1); ...
yubのAlgorithm0.0
闲言碎语 思来想去还是想把之前打卡的内容搬过来(毕竟博客修修补补还是勉强可以凑合看 笑)还是作为自己的点滴记录吧.【是的看到的日期一样的纯属是懒得改 不要学习懒惰】 wi师傅说毕设手搓一个自己的博客系统GitHub上能有几千star那包过的,倒是有这么个想法,说不定自己哪天也可以实现呢. 之后搬运过来的内容也算是复习了,希望自己能在薄弱的方面越来越好.【这个时候在Harmony开发课上插着耳机一个人passion hh】
希望自己这次能真正坚持下来.(在学习的学弟学妹们也继续加油哦 期待你们成为自己理想中的pwn✌)
共勉.
Java多线程_0x9_
多线程篇九常见的锁策略虽然我们开发者一般只关注如何使用锁,但设计锁我们也需要有一定的了解.
乐观锁和悲观锁顾名思义,两个锁一个是考虑的最优情况一个考虑最坏情况.
乐观锁在加锁之前,假设数据一般情况下不会产生冲突,只在数据进行返回更新的时候进行检查校验,如果发生并行冲突就返回错误信息,让用户重新进行决策.(就是加锁之前预估出现所冲突的概率不大所以在加锁前不会进行太多的工作【加锁过程做的事少加锁的速度更快但是更容易引入一些其他问题消耗CPU资源】)比如你想吃饭,但是食堂这个时候被军爷占领了,你觉得你去的过够早军爷抢不过你,直接冲去食堂,结果排上了长长的队伍.【没加锁但能识别数据冲突】
悲观锁在加锁之前,总假设数据从一开始就容易被修改,每次拿数据的时候就会加锁.想拿到这个数据只能等待阻塞拿到锁.(在加锁之前预估出现锁冲突的概率很大,加锁的时候会做更多的工作防止意外,此时加锁的速度可能更慢,但是整个过程中更不容易出现其他问题)和上述同样的情况,为了防止空跑一趟你给可预定窗口发消息询问能否预定(相当于加锁)得到肯定答复之后会来取餐如果生意太火爆没回或者说不够预定的就下次再去这个窗口.
Synch ...
Java多线程_0x8_
多线程篇八线程池什么是线程池?顾名思义,线程池是一个存放了很多线程的池子.既然有很多线程,那一定很方便调用对吧,有很多线程那大家一定喜欢一起玩吧(并发).
线程池是一种并发编程中常用的技术,用于管理和重用线程.线程池由线程池管理器、工作队列和线程池中的线程构成.
线程池的优点由于进程的频繁创建和销毁带来的巨大开销,所以聪明的大佬们选择引入线程池或者更轻量级的协程(纤程).协程的本质室程序员再用户态代码中进行调度,不依赖内核.纯用户态代码是基于线程封装过来的就比内核调用更加安全.而引入线程池就能**减少每次启动、销毁线程的损耗.**【用完了也不用销毁,多次利用,喜欢用一辈子的奥特乐袋子!(bushi】
标准库中线程池Tips
corePoolSize: 核心线程数(一个线程池里,最少有多少个线程)maximumPoolSize :最大线程数(一个线程池中,最多有多少个线程)keepAliveTime:线程空闲超过这个时间阈值,就会被销毁unit:时间单位,取分钟,秒,小时等等workQueue:和定时器相同,线程池也可以有很多任务,也可以设置为带有优先级的ThreadFactory: 线 ...