经典专题
文章平均质量分 81
物以类聚,题以群分。
samarua
while "live" : print("Loli")
展开
-
【经典专题】数组中出现1次/2次的数字——垂直方向的位运算
问题引入有一个数组:nums = [2, 2, 3, 3, 6, 6] 。它具有怎样的性质呢?所有元素异或和为0。这个位运算好像很简单?别着急,接下来,我们将要把位运算发挥到极致。 情境壹——num出现一次,其余元素出现两次一个数组nums里除某个数字之外,其他数字都出现了两次。找出这个数字。不假思索,一气呵成。class Solution { public int singleNumber(int[] nums) { int res =原创 2021-08-09 18:33:13 · 257 阅读 · 1 评论 -
【经典专题】经典中的经典——TopK问题
问题引入请找出一堆数据中,最小/最大的k个数。题目描述非常简单,你有多少种思路去实现它呢? 解法1——朴素排序首先可以想到一种非常朴素的思路:将数据从小到大进行排序,取其前k个数即可。不多赘述,直接看代码:class Solution { public int[] getLeastNumbers(int[] arr, int k) { // 排序 Arrays.sort(arr); // 取前k个数 in原创 2021-08-08 14:04:36 · 323 阅读 · 0 评论 -
【经典专题】数据结构的组合扩展——从双边队列到单调队列
问题引入你能否定义一个队列,这个队列不仅拥有 push_back 和 pop_front 这两个队列原生函数,还能够通过 max_value 函数 O(1) 的获取队列中的最大值。给个小提示 >_<,你可以用两个队列来组合实现它。 类比思考我们解决过这样一个更加简单的问题:用两个栈实现一个具有min()功能的栈。数据栈存放原始数据,辅助栈是一个单调栈,其栈顶元素即为min值…在 push 的时候,维护这个单调栈;在 pop 的时候,同时进行双栈的同步…有思原创 2021-08-06 16:56:26 · 143 阅读 · 0 评论 -
【经典专题】分割整数得到最大乘积——剪绳子问题
问题引入给你一根长度为 n 的绳子,请把绳子剪成整数长度的若干段,然后把各段长度相乘,能得到的最大乘积是多少?(注:长度n至少为2,你至少要剪一次)举个例子:绳子长度为10,那么我们把它剪成 3+3+4 的多段,可以得到最大值 3×3×4=36 。 初步结论2 = 1 + 1,1 × 1 = 12不应该被切3 = 1 + 2,1 × 2 = 23不应该被切4 = 2 + 2,2 × 2 = 44切不切都一样5,6,7,8,9…原创 2021-07-31 16:52:39 · 774 阅读 · 0 评论 -
【经典专题】最简单的题目也能脑洞大开——字符串找不同
Q:给出一个字符串s,将其随机排序后再随机新加一个字母,得到新的字符串t——你能找到那个新加的字母吗?(s,t均由小写字母组成)Input:s = “abcd”, t = “abocd”OutPut:‘o’ 异或class Solution { public char findTheDifference(String s, String t) { int res = 0; for(char c : s.toCha.原创 2021-07-31 16:52:04 · 140 阅读 · 0 评论 -
【经典专题】从模板到本质——背包问题
算法定义背包问题(Knapsack problem)是一种组合优化的NP完全问题。问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。不想看定义?那么接着看下面的通俗栗子:给定一个nums[]数组,再给定一个背包容量target,你能否用nums[]中的物品装满背包呢? 问题分类首先,根据数组中的元素是否可以重复使用,背包问题分为:❶ 0-1背包:数组中的元素不能重复使用❷ 完全背包:数组中的元素可以重原创 2021-06-26 11:09:14 · 310 阅读 · 0 评论 -
【经典专题】和为K问题——双重for循环的哈希降维
两数之和我们先从一个极其简单 的问题开始吧!给定一个整数数组nums和一个目标值target,数组中是否存在两个数,它们的和为target?举个例子,nums=[5, 3, 1, 2, 6],target=9,那么存在这样的两个数(3,6),它们的和为9。你立即有了思路,然后写出代码一气呵成:class Solution { public boolean twoSum(int[] nums, int target) { for (int i = 0; i < num原创 2021-06-26 10:41:40 · 226 阅读 · 0 评论 -
【经典专题】数字与罗马数字的转换——罗马数字的计数本质
问题引入你了解罗马数字吗?罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。举几个栗子:LVIII = L + V +III = 50 + 5 + 3 = 58MXLIV = M + XL + IV = 1000 + 40 + 4 = 1044 问题1:数字转罗马数字解法一:贪心+哈希对于数字num,使用贪心的思路,剥离下来从大到小的数字。同时我们还要借助一个哈希表。class Solution { public String intTo原创 2021-05-21 16:16:47 · 512 阅读 · 0 评论 -
【经典专题】强大的性质与惊艳的解法——异或运算
异或运算简介符号异或运算即exclusive OR,通常写作XOR,数学符号⊕,程序符号^。运算相同为0(1^1=0, 0^0=0),不同为1(1^0=1, 0^1=1)性质① 自反性:a ^ b ^ b = a② 无序性:a ^ b ^ c ^ d = b ^ d ^ a ^ c③ 可移项性:a ^ b = c 可移项为 a = b ^ c,移项时无需改变符号④ 位独立性:每一位的异或互相独立,比如 1010 ^ 1110 = 0100 题目1:原创 2021-05-18 15:41:25 · 4999 阅读 · 4 评论 -
【经典专题】给工人分配工作——回溯优化连环问
题目描述给你一个整数数组 jobs ,其中 jobs[i] 是完成第 i 项工作要花费的时间。请你将这些工作分配给 k 位工人。如何尽快完成这些工作?请给出你的解决方案。示例:jobs = [1, 2, 4, 7, 8], k = 2解释:1 号工人工作时间为 1 + 2 + 8 = 11,2 号工人工作时间为 4 + 7 = 11,最终工作完成时间是 11 。 基本思路回溯法。其实就是暴力,试探出所有的分配情况,分配完所有工作后(index == jobs.lengt原创 2021-05-09 16:53:54 · 173 阅读 · 0 评论 -
【经典专题】区间DP的经典代表——回文串问题汇总
回文串模板首先,回文串问题的核心就是 if(s.charAt(i) == s.charAt(j)) {dp[i][j] == dp[i + 1][j - 1]}原创 2021-04-19 20:39:14 · 942 阅读 · 0 评论 -
【经典专题】多出的一维k遍历——升阶版的区间DP
区间DP简介区间DP区别于普通DP的特征是:dp[i][j]表示的是从i到j的闭区间 。比较典型的区间DP有:字符串匹配问题、回文子串问题。今天要说的区间DP,会更进一步,使用更高维的 dp[i][j][k] 。但是,本质仍旧是区间DP问题。 区间DP模板动态规划是没有模板的。但是,区间DP有着比较固定的 填表顺序 :体现在代码里是这样的:for (int j = 1; j < len; j++) { for (int i = j - 1; i >=原创 2021-04-17 16:02:28 · 138 阅读 · 0 评论 -
【经典专题】丑数问题——因子问题的延伸思考
概念引入只包含质因子2,3和5的数称作丑数(Ugly Number)。比如10是丑数,14不是丑数。另外,1通常被认为是丑数。从定义还可以看出,0和负整数一定不是丑数。前20个丑数为:1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 25, 27, 30, 32, 36。 问题一:判断一个数是否是丑数根据定义可以直接AC该题:让这个数n反复除以2、3、5,直到其不再包含因数2、3、5。若剩下的数是1,则n为丑数。原创 2021-04-12 09:00:47 · 414 阅读 · 0 评论 -
【经典专题】旋转排序数组——以nums[right]为关键的二分
概念引入旋转排序数组 就是一个递增数组(暂且不论严格/非严格)在某一个点处进行了旋转。为了避免“旋转”这个词的歧义,下面用一个例子直观展示:原递增数组:[1, 2, 3, 4, 5, 6, 7]旋转后数组:[4, 5, 6, 7, 1, 2, 3] 性质分析第一点:旋转多次等价于旋转一次不要被“旋转”这两个字误导,透过现象看本质,所谓的 旋转 其实就是 循环移动 —— 你看成循环左移/循环右移都可以,本质还是 模(mod)。在纸上写写画画,比凭空想象有用。第二点:原创 2021-04-09 16:23:25 · 495 阅读 · 0 评论 -
【经典专题】推箱子游戏脚本——一次BFS与多次DFS
题目引入推箱子 是一款风靡全球的益智小游戏,玩家需要将箱子推到仓库中的目标位置。游戏地图用大小为 n * m 的网格 grid 表示,其中每个元素可以是墙、地板或者是箱子。现在你将作为玩家参与游戏,按规则将箱子 ‘B’ 移动到目标位置 ‘T’ :玩家用字符 ‘S’ 表示,只要他在地板上,就可以在网格中向上、下、左、右四个方向移动。地板用字符 ‘.’ 表示,意味着可以自由行走。墙用字符 ‘#’ 表示,意味着障碍物,不能通行。箱子仅有一个,用字符 ‘B’ 表示。相应地,网格上有一个目标位置 ‘T’原创 2021-04-08 00:39:45 · 1182 阅读 · 3 评论 -
【经典专题】dp表的降维优化——滚动数组与强行滚动数组
问题引入哪种情况下可以可以对dp表进行滚动数组优化?直观的讲,在某一维度的跨度仅仅是1的时候(出现 i - 1 或者 j - 1 ),就可以直接删掉一维,即进行滚动数组优化。滚动数组优化的代码怎么写?由于滚动数组会让原先清晰的动态规划逻辑变的莫名其妙,因而最后不要想着一步到位、直接写低维dp。而是直接在原先代码的基础上删掉一维即可。可是,这种屡试不爽的思路每用10次翻车1次,究竟是为什么呢?看来,上面这种“一维跨度”的思路并没有触及到滚动数组的本质,是一个错误的认知。下面,将用一个极为典型的例题原创 2021-04-03 11:30:13 · 845 阅读 · 3 评论 -
【经典专题】从此开始玩转二分——B模板:收缩
二分法看似千变万化,但都可归纳为两种模板。命中模板——目标值已有确定值。万军丛中只此一个目标,便可一击命中。收缩模板——目标值还未确定,只知道它所符合的条件。前面一堆false,后面一堆true,真正的目标是第一个true。 这篇文章介绍第二种,所谓“收缩”。 二分模板(B模板)// × × × × × √ √ √ √ √ 找第一个符合条件的元素class Solution { public int search(int[] nums) { .原创 2021-03-29 21:31:49 · 148 阅读 · 0 评论 -
【经典专题】从此开始玩转二分——A模板:命中
二分法看似千变万化,但都可归纳为两种模板。命中模板——目标值已有确定值。万军丛中只此一个目标,便可一击命中。收缩模板——目标值还未确定,只知道它所符合的条件。前面一堆false,后面一堆true,真正的目标是第一个true。 这篇文章介绍第一种,所谓“命中”。 二分模板(A模板)public int search(int[] nums, int target) { int left = 0; int right = nums.length - 1;.原创 2021-03-29 21:31:23 · 110 阅读 · 0 评论 -
【经典专题】从一维到二维——从最大子数组到最大子矩阵
由简入难,先从最简单的问题的入手吧:给出一个整形数组,问最大子数组的和是多少?要求数组连续。输入样例:nums = [-3,4,-1,2,1,-5,4]输出样例:6,即连续子数组[4,-1,2,1]的和最大思路很简单:可以DP,但没必要。可以这样理解:当之前已有的数组和大于0时,则它必然对于此时的和有贡献,因此在其基础上累加(if sum > 0 : sum += nums[i]);当之前已有的数组和小于0时,则此时应该另起炉灶(if sum < 0 : sum = nums[i])。原创 2021-03-24 14:32:35 · 1715 阅读 · 6 评论 -
【经典专题】反转链表——如何在链表中穿针引线
反转整个链表(简单)很简单且经典的题目。就是将 1->2->3->4->5 反转为 5->4->3->2->1。有两种思路,迭代和递归。先看图再看代码:1)迭代——经典的双/三指针class Solution { public ListNode reverseList(ListNode head) { ListNode pre = null; ListNode cur = head; while原创 2021-03-18 15:29:41 · 374 阅读 · 0 评论 -
【经典专题】颠簸的波浪——摆动数组问题的标准答案
引入定义如果连续数字之间的差严格地在正数和负数之间交替,称为摆动数组。举几个例子。[1,7,4,9,2,5]是一个典型的摆动数组,它就像颠簸的波浪;[1,7,4,5,5]不是摆动数组,因为它不是严格的上下摆动;[1]和[1,5]都符合定义,是摆动数组。 题目两则Q1. 返回数组所包含的最大连续摆动数组的长度。 输入:[9,4,2,10,7,8,8,1,9]输出:5解释:[4,2,10,7,8]长度为2Q2. 返回数组所包含的最大摆动数组的长度,不要原创 2021-02-08 23:45:34 · 436 阅读 · 2 评论 -
【经典专题】爬行的毛毛虫——简单的滑动窗口模板
经典例题给你一个仅由大写英文字母组成的字符串,你可以将任意的字符替换成另一个字符,但最多可替换 k 次。在执行上述操作后,找到包含重复字母的最长子串的长度。 输入:s = “AABABA”, k = 1输出:4解释:将中间的一个’B’替换为’A’,字符串变为 “AAAABA”。 滑窗模板public int SlidingWindow(String s) { len = s.length(); // 串的长度 int[] count = new原创 2021-02-05 16:48:12 · 201 阅读 · 0 评论 -
【经典专题】图论两则——并查集/DFS/BFS/Dijkstra
最小阶梯的远足活动你参加了一次远足活动,并且有一张地图。地图是一个矩阵,height[i][j] 表示格子 (i, j)的高度。你有一个习惯,那就是在整段旅途中你不想走落差较大的阶梯,也就是说,一整条路径耗费的体力值是旅途中高度差绝对值的最大值决定的。 请你返回从左上角走到右下角的最小体力消耗值。 注:1 <= rows, columns <= 100,1 <= heights[i][j] <= 10^6 方法一——并查.原创 2021-02-01 14:47:35 · 249 阅读 · 2 评论 -
【经典专题】无序数组的最大间距(Max Gap)——线性的桶排序
Q:给定一个无序的数组,找出数组在排序之后,相邻元素之间最大的差值。 (请尝试在线性时间复杂度和空间复杂度的条件下解决此问题)input:6 12 2 4 3 17 11 5 10 output:5 思路分析先sort然后一次遍历,虽然简单直观但显然不满足O(n)排序如何才能降到O(n)呢?桶排序,用空间换时间!桶排序的两个经典问题:桶的宽度是多少?有多少个桶?似乎遇到了瓶颈。 深入理解想象一下,长度为(max−m.原创 2020-12-14 15:39:33 · 488 阅读 · 0 评论 -
【经典专题】链表的归并排序——经典的cut/merge模板
input:4 → 3 → 1 → 7 → 8 → 9 → 2 → 11 → 5 → 6 output:1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 → 9 → 11 核心知识点链表的截断(cut)链表的二路归并(merge)虚拟头节点(dummyHead),滞后指针(pre)等小技巧 模板▍快慢指针找中间节点private ListNode findMid(ListNode head){ if(head.原创 2020-12-14 09:44:58 · 271 阅读 · 0 评论 -
【经典专题】寻找质数——巧妙的埃氏筛和线性筛
很经典的题目:统计 [2,n)[2,n)[2,n) 中质数的数量Demo1:input 10,output 4Demo1:input 100,output 25 暴力枚举首先,复习一遍质数的定义:在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。最朴素的思想,对于一个数 nnn,把它除以 [2,n)[2, n)[2,n)的每一个数,如果出现了整除的情况(n % i == 0),则 nnn 即为质数。这种纯暴力的方法(考虑最坏的情况),判断每个数的时间.原创 2020-12-12 19:02:21 · 240 阅读 · 0 评论