115 | 给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。 s = "rabbbit", t = "rabbit" | 思路:dp[i][j]表示s[0~i] 与 t[0~j]有几种匹配结果 dp[i][j] = dp[i-1][j] //无论什么时候都可以将第i位删掉,去查看s[0/i-1]与t[0/j]的匹配 此外当第i位与第j位匹配的时候,还可以加入s[0/i-1] 和 t[0/j-1]的匹配情况 因此 dp[i][j] = dp[i-1][j] + (dp[i-1][j-1] if s[i] == t[j]) |
给定n位,每一位可以选0-9,总共的选法。一共肯定是有10^n种 | 1、可以循环n次 2、可以使用递归 | |
15 | 三数之和 | 先排序,固定一个数可以转换为两数之和,使用双指针。注意去重i,j,k的重复 |
10 | 正则表示式匹配 | 到着看,*只能是将前一个数重复0 1 ……次。看手画图解 |
92 | 反转链表 反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。 说明: | 1、新建节点的方式,从pre开始遍历到last,每次都在last后面新建节点,最后把pre到last删除就好 2、修改next值,记录pre的下一个prenext,每次将prenext指向pre,更新pre 和prenext的值 注意判断m=1的情况,也就是把原来的头节点删了 |
31 | 下一个排列 算法需要将给定数字序列重新排列成字典序中下一个更大的排列。 | 思路:下一个大的排列,肯定是将某个大的数换到了前面,因此要找下一个最大的,就找最后一个升序的对儿,123476,比方找到了最后的是4-7和4-6,最后一个对是4-6,因此将4-6交换得到674,将74正序排序,就得到最终结果 |
32 | 最长有效括号 给你一个只包含 | 思路:将括号压栈,左右括号匹配时就弹栈,最后栈里剩下的序列,间隔最大的差就是最长的括号长度 比如左边题最后栈里剩 0 5,因此05之间的括号都是匹配的,所以最长的就是5-0-1 = 4 注意: 1、当栈为空或当前时'('就压栈。2、当前是右括号就与栈顶匹配,如果匹配到左括号就弹栈,3、否则就把右括号压栈 第3步一定要注意!!! |
153 | 没有重复元素 假设按照升序排序的数组在预先未知的某个点上进行了旋转。请找出其中最小的元素。 | 二分做,基于一个定论 mid跟right比,如果nums[mid] > nums[right],那么转折点一定在mid右边,所以left = mid + 1 如果nums[mid] < nums[right] 那么从mid到right一定是升序的!但mid也可能是转折点,因此left = mid |
154 | 有重复元素 假设按照升序排序的数组在预先未知的某个点上进行了旋转。请找出其中最小的元素。 | 基于上面的定论,因为此时如果nums[mid] == nums[right],我们分不清是在左边还在右边,但无论是哪边,nums[right]在数组中有个相同的数nums[mid],因此就把nums[right]删掉,缩小边界 因此由二分变成三分 |
76 | 最小覆盖子串 给你一个字符串 | /* 1、见到子串要想到滑动窗口 2、滑动窗口永远设置都是right的还没往进加的,所以进入循环后第一步就是将s[right++]加到窗口中 3、计算窗口长度时,要记住此时right是已经递增过1的,所以窗口长=right-left */ 使用滑动窗口,使用两个map记录窗口和子串中的字符个数。只要当前的滑动窗口中包含了子串t中的所有字符,那么就是一个有效值,只是需要收缩左侧来得到最小字符串 |
121 | 买卖股票的最佳时期 | 看labuladong的题解,注意如果表示-1天的话,dp[-1][k][0] = 0. dp[-1][k][1] = INT_MIN 如果表示第0天的话,dp[0][k][0] = 0, dp[0][k][1] = -prices[0] |
82 | 删除链表中的重复元素 给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字 | 我的思路与其类似,也是先找一个cur,之后比较cur.next 和 cur.next.next * 不同的是,我每次删除的是cur.next.next,让cur.next.next指向新的节点 * 而本思路是如果cur.next == cur.next.next,记录cur.next.val的值 * 每次去改变cur.next,如果等于x就让cur.next指向下一个 * 思路比我的要简单 |
341 | 扁平化嵌套列表 列表中的每一项或者为一个整数,或者是另一个列表。其中列表的元素也可能是整数或是其他列表。 | 1、递归,在类构造时就使用递归将列表扁平 2、循环+栈,在每次判断hasNext时将列表扁平(将列表从后向前压入栈,就能使得打印栈顶时是由前到后的) |
198 | 打家劫舍问题汇总 | 打家劫舍问题汇总 |
56,1288 986 | 区间覆盖,删除,交集等操作 | 一般都是先按左边界排序,之后看区间左右的端点的关系,看lubuladong的文章 |
460 | LFU缓存设计 淘汰最近最少使用 | 设置三个hash unordered_map keyToFreq; unordered_map keyToNode; unordered_map freqToKeys; |
142 | 寻找环形链表的入口 | 先找到相遇的点,之后一个点从head开始,一个点从相遇点开始,相等的点就是入口点 |
1109 | 航班预定统计 前缀数组和差分数组 | 前缀数组适合数组元素不变,但是要多次计算数组某一区间和的情况 差分数组适合数组某一区间元素不断改变,最后求数组中的值到底是多少 |
207 | 课程表设计 | 拓扑排序解法 |
最小生成树 | kruskal算法和prim算法 这算法是将图中所有顶点连接起来的最短边和,n个顶点,n-1条边 | |
最短路径 | Dijkstra算法和Floyd算法 这是找图中某一点到其他点的最短路径,最短路径并不意味着是最小生成树。 | |
847 | 旅行商问题 | 再看看 |
72 | 编辑距离(对一个字符串 增删改 变为另一个字符串) | 这题用dp,dp[i][j]表示,word1的0-i转为word20-j的步数, dp[i-1][j-1]表示修改,dp[i-1][j]表示对word2增加一位(即是对word1减去最后1位),dp[i][j-1]表示对word1增加一位 此题和127单词接龙不一样,单词接龙是指将一个word按照word list的规则转为word2,这题用图的BFS做 |
75 | 颜色分类,荷兰国旗问题 | 此题可以抽象为,给定一个值K,要求把数组中小于K的元素放到数组的左边,大于K的元素放到数组的右边 看起来很像qsort的每一步,但是qsort只是每次把首位的数放到正确的位置pos,也就是保证pos之前的数都小于首位,pos之后的数都大于首位,但是并不保证pos之前 之后的数是不是顺序的,0 1 0 2 3 2 3,此时的pos在3,确实保证了上述条件,但两侧都是无序的。 而荷兰国旗问题,比qsort的每一步要更进一点,它会保证K元素在中心,小于K的在左边,大于K的在右边,但是不保证小于 或者 大于的数是有序的。 |
470 | 用rand7生成rand10 | 用randa生成randb if(a > b) 比方说rand10生成rand7,只要产生的数大于7就重新产生 if(a < b) 可以用7*(rand()-1) + rand7()生成1-49的随机数,再生成rand10 用randa,randb生成randab随机数,比方用rand7,rand10生成rand70的 方法1、7*(rand10() - 1) + rand7() 方法2、10*(rand7() - 1) + rand10() |
81 | 搜索旋转排序数组II 在旋转的排序数组中搜索target,而不是找旋转点 | 思路: 1、先确定mid的位置,mid跟nums[j]比较,确定mid在前半段还是后半段 2、确定target的位置,a) mid在前面,target < nums[mid]有两种情况,target在mid前面和target在后半段 b) mid在后面,target > nums[mid]也有两种情况,target在mid后面和target在前半段 通过比较target和nums[j[的值确定target的位置 |
最大公约数,最小公倍数 | 最大公约数: 1、辗转相除法,a是两数种较大,b是两数中较小,a与b的最大公约数 = (a %b)与 b的最大公约数 2、更相减损术,a是两数种较大,b是两数中较小,a与b的最大公约数 = (a - b)与 b的最大公约数 3、可以判断两数的奇偶,选择位选算来加速 最小公倍数: a与b 的乘积 = a与b的最大公约数 * a与b的最大公倍数 ab最小公倍数 = a*b / c (c是ab的最共公约数) | |
28 | 字符串匹配 | KMP算法 |
368 | 最大整除子集 | 类似于最大递增子序列 每次到一个i的时候,都去和i前面的所有j去比较 不同的是,递增子序列比较的是大小,这个题比较的是能否整除 具体看题解 |
4 | 寻找两个正序数组的中位数 | 简单的方法就是转为找第k = len/2大个元素,在两个数组中建立两个指针,(如果一个数组为空,或者该数组当前值大于另一个数组的当前值,那么就在另一个数组中找),因为可能是偶数要找两个值嘛,所以用left和right记录,每次移动的时候先用left来记录right,再将right移动。如果len是奇数,那么直接返回right,如果是偶数,那么就返回(left+right) / 2.0,见提交记录 复杂的方法是进行两个数组中进行一半一半的比较,将时间复杂度降为O(log(m+n)),见提交记录 |
743 | 图的最短路径问题 | 1、迪杰斯特拉算法:算法的关键是使用一个最小堆,每次从最小堆中取出最小的 2、Floyd算法:记住一定要先初始化矩阵!! |
46 | combination和permutation | permutation的时间复杂度是O(n*n!),其中n!是递归树的n!个叶子节点,n是每次将一种可行解放入ans的时间 combination的时间复杂度是O(n*2^n) 其中2^n是每个数可选可不选的情况,n是每次将一种可行解放入ans的时间,这是最坏的时间 |
1838 | 最高频数 | 看题解,将k作为滑动窗口的阈值,频数是滑动窗口的长度,每次右移窗口时,窗口中的总操作total会改变,与k进行比较。 看官方题解。 |
227 | 基本计算器 | 对于式子1+2*3+4 思路就是遇到+ -时,直接将数字压入栈,遇到* /时,将数字与栈顶元素进行运算 主要有很多细节需要注意: 1、只有数字的情况 2、最后一个数字的情况 将式子转为 +1+2*3+4 对于每一个数字,前面的那个符号就是其自己的符号 |
662 | 二叉树的最大宽度(空节点也算宽 ) | 对每个节点进行编号,左孩子=index*2 +1, 右孩子=index*2 + 2.每一层的宽度就是队列中最左侧节点与最右侧节点的差 |
384 | 随机打乱数组 | 1、交换法 2、每次产生随机数的时候只产生i~back的随机数 rand()%(size - i) + i 对于nums = {1, 2, 3, 4, 5} 对于第0位,任意的rand()%5放在第一位都可以满足1/5,比方是3,那么1和3进行交换 {3, 2, 1, 4, 5} 对于第1位,rand()%4 + 1,选取{2, 1, 4, 5},概率是 4/5 * 1/4 = 1/5, 4/5是指不能选3,只能在2145中选 自然就是4/5 对于第2位,3/5 * 1/3 = 1/5 |
705 | 设计哈希集合 | 使用vector<list<int>> 来模拟拉链法哈希表 hash表长度选择,即尽量选择素数,这样可以最大程度上避免冲突 也有hash表长度len选择为2的幂,这是因为key%len = key & (len - 1),主要是考虑了位运算的操作比较快 同时注意对vector中list操作时,注意迭代器失效的问题 |
29 | 不使用/, *, %来计算两个数的除法 | 思想:不断减去 减数求得商,可以使用翻倍来加速 60/8 = (60 - 32 - 16)/8 + 4 + 2 = 1 + 4 + 2 = 7 |
560 | 这个数组不是有序的,特别容易想成滑动窗口,因为滑动窗口默认i++是变小,j++是变大。但这题中的数组不是有序的。因此用前缀和+map。pre[i]是0-i个数的和,所以说在map中如果存在pre[i]-k,那么就一定存在一个j,0-j的值是pre[i]-k。所以i-j的值就是k pre[i] - (pre[i] - k) = k | |
Hot100
最新推荐文章于 2023-07-02 11:03:41 发布