代码随想录刷题
数组二分查找二分查找这道题目的前提是数组为有序数组,同时题目还强调数组中无重复元素,因为一旦有重复元素,使用二分查找法返回的元素下标可能不是唯一的,这些都是使用二分法的前提条件,当大家看到题目描述满足如上条件的时候,可要想一想是不是可以用二分法了。 二分查找涉及的很多的边界条件,逻辑比较简单,但就是写不好。例如到底是 while(left < right) 还是 while(left <= right),到底是right = middle呢,还是要right = middle - 1呢? 大家写二分法经常写乱,主要是因为对区间的定义没有想清楚,区间的定义就是不变量。要在二分查找的过程中,保持不变量,就是在while寻找中每一次边界的处理都要坚持根据区间的定义来操作,这就是循环不变量规则。 写二分法,区间的定义一般为两种,左闭右闭即[left, right],或者左闭右开即[left, right)。 12345678910111213141516public class Solution { public int Search(int[] nums,...
乐元素
1.好名字给定一个字符串,需要找出最长的连续子串(即“好名字”),满足条件: •在这个子串中,每个字符最多出现2次。 •并且最多只能有一个字符出现恰好2次(其他字符只能出现0次或1次)。 换句话说: •子串中所有字符的频率最多为2。 •并且至多有一个字符的频率为2(其他字符频率必须≤1)。 我们需要返回最长这样的子串的长度。 方法:滑动窗口(双指针)思路: 1.使用滑动窗口 [left, right]来代表当前子串。 2.用 freq数组(或哈希表)记录窗口内每个字符的出现次数。 3.维护两个关键计数: •countTwo`:记录当前窗口内出现次数恰好为2的字符的个数(应该最多为1)。 •countOver:记录当前窗口内出现次数超过2的字符的个数(应该为0)。 4.扩展右指针 right,增加字符,更新频率和计数。 5.如果当前窗口违反条件(即 countOver > 0或 countTwo > 1),则收缩左指针 left直到窗口再次合法。 6.在每一步中,如果窗口合法,更新最大长度。 注意: •由于条件要求最多一个字符出现2次,且没有...
一些基础的数据结构
动态数组 装箱:装箱是指将值类型转换为引用类型的过程。值类型(如 int、char、struct 等)通常存储在栈上,而引用类型存储在堆上。当进行装箱操作时,会在堆上为值类型创建一个对象实例,并将值类型的值复制到该对象中,最后返回这个对象的引用。 拆箱:拆箱则是将引用类型转换为值类型的过程。它需要先检查引用类型是否为某个特定值类型的装箱实例,然后将堆上对象中存储的值复制到栈上的新值类型变量中。 装箱开销:装箱操作会在堆上分配内存,并且需要复制值类型的值,这会带来一定的性能开销,尤其是在频繁进行装箱操作时,会导致内存分配和垃圾回收的压力增加。 拆箱开销:拆箱操作需要进行类型检查,确保引用类型确实是某个值类型的装箱实例,这也会带来一定的性能开销。 动态数组指的是是大小能在程序运行期间动态调整的数组,可根据实际需求增添或删减元素。与固定大小的数组不同,动态数组能够灵活应对元素数量的变化,从而更高效地管理内存。以下通过自定义的类实现动态数组,使用泛型类,来进行动态数组的实现,这样可以根据数组的类型,实现相应的功能,同时实现IEnumerable接口,可以被foreach循环遍历...
LeetCode-Hot100
哈希表两数之和 解答一:使用暴力算法 12345678910111213public int[] TwoSum(int[] nums, int target) { int[] arrs = new int[2]; for(int i = 0; i < nums.Length; i++) { for(int j = i + 1; j < nums.Length; j++) { if(nums[i] + nums[j] == target) { arrs[0] = i; arrs[1] = j; return arrs; // 找到后立即返回,提升效率 } } } return arrs;} 解答二:使用字典 12345678910111213141516public class Solution ...
KMP和Manacher算法
Manacher算法 预处理:统一奇偶长度 回文串有奇数长度(如”aba”)和偶数长度(如”abba”)之分,这会给统一处理带来麻烦。 Manacher算法通过在原始字符串的每个字符之间以及首尾插入一个原字符串中不存在的特殊字符(通常用#)来进行预处理。例如,"abba"会被处理成 "#a#b#b#a#"。 这样做的好处是:无论原字符串如何,新字符串的长度总是奇数,所有回文子串都变成了奇数长度,从而可以统一以每个字符为中心进行扩展检查。 利用回文对称性 算法维护一个回文半径数组 P(也称为辅助数组),P[i]表示以新字符串中第 i个字符为中心的最长回文子串的半径(包含中心字符本身)。例如,对于字符串 "#a#b#a#",以中间的 b(位于索引4)为中心,其回文半径是4。 关键在于,算法在从左至右遍历字符串时,会动态维护一个当前已知的最右回文边界 R 以及达到该边界的中心位置 C。 当遍历到位置 i时,如果 i在当前最右边界 R之内,则可以找到 i关于中心 C的对称点 j。根据回文的对称性,可以利用 P[j]的值来快速...
2叉树
12345678910* public class Node {* public int val;* public Node left;* public Node right;* public Node(int val=0, Node left=null, Node right=null) {* this.val = val;* this.left = left;* this.right = right;* }* } 非递归实现遍历使用栈进行先序遍历 头 - 左 - 右1234567891011121314151617181920public List<int> presort(Node head){ List<int> result = new List<int>(); Stack<Node> nodes = new Stack<Node>(); if (...
Task-Async-Await学习笔记
C# 异步学习笔记(Task / async / await)1. 核心概念 Task:表示一个将来会完成的操作。 Task<T>:表示将来会完成并返回 T 的操作。 async:修饰方法,表示方法内部可使用 await。 await:异步等待,不阻塞当前线程。 关键理解:异步不等于多线程。Task 不是线程本身,而是“未来结果”的抽象。 2. Task 的状态Task 最终会进入以下三种状态之一: RanToCompletion:成功完成。 Faulted:失败并携带异常。 Canceled:被取消。 3. async/await 执行机制异步方法会先同步执行,直到遇到第一个尚未完成的 await 才挂起。任务完成后,方法从 await 后继续执行。 12345public async Task<int> GetNumberAsync(){ await Task.Delay(500); return 42;} 4. 返回类型选择 推荐:Task / Task<T>...
第一篇文章
这里是 Hexo + Butterfly 个人博客的第一篇占位文章。 后续可以把这里替换成你的个人介绍、游戏客户端开发笔记、Unity 项目复盘,或者「岁迹 LifeAtlas」的开发日志。