yubのAlgorithm.0x5
反转链表link:206. 反转链表 - 力扣(LeetCode)
思路分析与数组不同,链表没必要定义新的链表进行存储【对内存空间的浪费】直接改变next指针即可.注意头节点指向的下一个节点为null
双指针法123456789101112131415161718class Solution { public ListNode reverseList(ListNode head) { //双指针操作 ListNode prev = null; ListNode cur = head; //记录节点 ListNode temp = null; while(cur != null) { temp = cur.next;//保存下一个节点 cur.next = prev; //赋值之后整体向后移动//注意先移动prev 不如cur已经移动后记录不到prev新的位置 prev = cur ...
yubのAlgorithm.0x4
移除列表元素link:203. 移除链表元素 - 力扣(LeetCode)
首先单向链表是有一个数据域和指针域且在内存中不连续.链表的查找需要从头往后一个个查找【时间复杂度为O(n)】,但是数组查找只需要访问对应元素下标即可【时间复杂度为O(1)】.查找频繁:数组是更好的选择,因为通过索引访问的时间复杂度是 O(1),链表则需要遍历.
插入/删除频繁:链表更适合,因为它可以高效地插入和删除元素,时间复杂度为 O(1)(假设已找到插入或删除位置)。相反,数组在插入和删除时需要移动大量元素,时间复杂度为 O(n).
思路分析看到题目最第一反应就是常规解法,遍历链表找到target直接进行删除操作.【目标是头节点和不是头节点两种情况】(其实还是想有更优雅的解法 不用单独处理移除头节点的情况)
直接删除1234567891011121314151617181920212223class Solution { public ListNode removeElements(ListNode head, int val) { if(head == null)& ...
yubのAlgorithm.0x8
两个数组的交集link:349. 两个数组的交集 - 力扣(LeetCode)
思路分析首先想到合并两个数组,遍历找重复项存储到新的数组中但其实用HashSet是更加方便的,【HashSet不存在重复数据】
**注意:使用数组做哈希表的题目都限制了大小 例如只有小写字母或者数值大小在【0-1000】内 **
HashSet12345678910111213141516171819202122232425262728293031import java.util.HashSet;import java.util.Set;class Solution { public int[] intersection(int[] nums1, int[] nums2) { if(nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0 ) { return new int[0]; } //创建需要的set表 ...
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.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.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.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.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.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); ...