1 | 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。 |
1 | /** |
1 | 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。 |
1 | /** |
1 | class Solution { |
1 | import java.util.HashMap; |
要想解决本题,首先需要了解一个简单的结论:
对于 $n$ 个不同的元素(例如数 $1, 2, \cdots, n$),它们可以组成的排列总数目为 $n!$。
对于给定的 $n$ 和 $k$,我们不妨从左往右确定第 $k$ 个排列中的每一个位置上的元素到底是什么。
我们首先确定排列中的首个元素 $a_1$。根据上述的结论,我们可以知道:
由于我们需要求出从小到大的第 $k$ 个排列,因此:
$a_1 = \lfloor \frac{k-1}{(n-1)!} \rfloor + 1$
其中 $\lfloor x \rfloor$ 表示将 $x$ 向下取整。
当我们确定了 $a_1$后,如何使用相似的思路,确定下一个元素 $a_2$呢?实际上,我们考虑以 $a_1$为首个元素的所有排列:
其中 $[1,n] \backslash a_1[1,n]$表示包含 $1, 2, \cdots n$ 中除去 $a_1$ 以外元素的集合。
这些排列从编号 $(a_1-1) \cdot (n-1)!$开始,到 $a_1 \cdot (n-1)!$结束,总计 $(n-1)!$个,因此第 $k$ 个排列实际上就对应着这其中的第$k’ = (k-1) \bmod (n-1)! + 1$个排列。这样一来,我们就把原问题转化成了一个完全相同但规模减少 1 的子问题:
求 $[1, n] \backslash a_1$这 $n-1$ 个元素组成的排列中,第 $k’$小的排列。
1 | import java.util.Arrays; |
参考文献
1 | 作者:LeetCode-Solution |
1 | 作者:liweiwei1419 |
难度: 中等
根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
1 | 前序遍历 preorder = [3,9,20,15,7] |
返回如下的二叉树:
1 | 3 |
根据前序遍历找根,(使用哈希表记录中序遍历每个元素的index)根据根找左子树的元素和右子树的元素
难度在于处理边界条件
1 | /** |
1 | 给定一个二叉树,原地将它展开为一个单链表。 |
1 | /** |
难度简单
一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,替按摩师找到最优的预约集合(总预约时间最长),返回总的分钟数。
注意:本题相对原题稍作改动
示例 1:
1 | 输入: [1,2,3,1] |
示例 2:
1 | 输入: [2,7,9,3,1] |
示例 3:
1 | 输入: [2,1,4,5,3,1,1,3] |
对于每个客人有两种选择:
选择和不选择
没选择时:上一次可以选了,也可以没选,求两种情况的最大值
选择时:上一次没选+本次选的,上上次选了,求两种情况的最大值
1 | class Solution { |
1 |
|
1 | public int lowbit(int x) { |
1 | public void init(int n){ |
1 | // 查找根节点这句的理解 |
1 | public class Trie { |
Trie (发音为 “try”) 或前缀树是一种树数据结构,用于检索字符串数据集中的键。这一高效的数据结构有多种应用:
还有其他的数据结构,如平衡树和哈希表,使我们能够在字符串数据集中搜索单词。为什么我们还需要 Trie 树呢?尽管哈希表可以在 O(1) 时间内寻找键值,却无法高效的完成以下操作:
核心就是对拼消耗。玩一个诸侯争霸的游戏,假设你方人口超过总人口一半以上,并且能保证每个人口出去干仗都能一对一同归于尽。最后还有人活下来的国家就是胜利。那就大混战呗,最差所有人都联合起来对付你(对应你每次选择作为计数器的数都是众数),或者其他国家也会相互攻击(会选择其他数作为计数器的数),但是只要你们不要内斗,最后肯定你赢。最后能剩下的必定是自己人。
作者:胡新辰来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
先向右扩展窗口,当窗口的值满足条件时,收缩左边界,并记录所要求的最优质,直至窗口内的值刚好满足条件。 然后继续向右移动右边界,收缩左边界,$…$
思路:不管上车人是谁,也不管下车人是谁,上车的时候加人,下车的时候减人。然后遍历行程序列,对路途中的在行程中的人数计数,如果大于capacity就不能顺利接收
思路:对于每个节点维护一个入度数组,如果入度数组的值为0,将其加入队列。从队列取出元素,将依赖该节点的所有节点的入度减一,如果某个节点的入度为0,那么将该节点加入到队列中去。
在这个过程中记录每次出队的元素即为拓扑排序的顺序,如果最后排序完的数量小于原始节点的数量,那么无法完成拓扑排序
思路:一个快指针 $f$ 每次走两步,一个慢指针 $s$ 每次走一步,如果快指针和慢指针相遇了 $(f==s)$ ,那么说明链表存在环路
思路:快指针 $f$ 每次走两步,慢指针 $s$ 每次走一步,快慢指针相遇的时候 $(f==s)$ ,一个每次走一步的慢指针 $ps$ 从头节点出发,当慢指针 $s$ 与 $ps$ 相遇的时候,就是第一个进入环路的节点
思路:两个节点同时走,即指针 $P_A$ 走 $A$ 链表,指针 $P_B$ 走 $B$ 链表,$P_A$ 走到末尾时,切换到B链表上,$P_B$ 走到末尾时切换到 $A$ 链表上,这时如果链表有交点,两个指针将会在交点相遇。
你变成我,走过我走过的路。
我变成你,走过你走过的路。
然后我们便相遇了..
或许这就是程序员的浪漫吧
对角线的计算方式是:
主对角线的计算方式是:$row-cloumn$ 在主对角线上的点的坐标的$row-column$的差值相同
副对角线的计算方式是:$row+column$在副对角线上的点的坐标的$row+column$的差值相同
模运算与基本四则运算有些相似,但是除法例外。其规则如下:
$(a - b) % p = (a % p - b % p) % p (2)$
$(a b) % p = (a % p b % p) % p (3)$
$a ^ b % p = ((a % p)^b) % p (4)$
结合律:
$((a+b) % p + c) % p = (a + (b+c) % p) % p (5)$
$((ab) % p c)% p = (a (bc) % p) % p (6)$
交换律:
$(a + b) % p = (b+a) % p (7)$
$(a b) % p = (b a) % p (8)$
分配律:
$((a +b)% p c) % p = ((a c) % p + (b * c) % p) % p (9)$
重要定理
若$a≡b (% p)$,则对于任意的$c$,都有$(a + c) ≡ (b + c) (%p);(10)$
若$a≡b (% p)$,则对于任意的$c$,都有$(a c) ≡ (b c) (%p);(11)$
若$a≡b (% p)$,$c≡d (% p)$,则
$(a + c) ≡ (b + d) (%p)$,
$(a - c) ≡ (b - d) (%p)$,
$(a c) ≡ (b d) (%p)$,
$(a / c) ≡ (b / d) (%p); (12)$
定义子问题$P(i,W)$为:在前$i$个物品中挑选总重量不超过$w$的物品,每种物品至多只能挑选1个,使得总价值最大;这时的最优值记作$dp(i,W)$,其中$1<=i<=n$ , $1<=w<=c$
考虑第$i$件物品,无外乎两种可能:选,或者不选。
最优方案就是比较这两种方案,哪个会更好些:
$dp(i,W)=max{dp(i-1,W),dp(i-1,W-w_i)+v_i}$
得到
$dp(i, W)=\left{\begin{array}{ll}
0 & \text { if } i=0 \
0 & \text { if } W=0 \
dp(i-1, W) & \text { if } w_{i}>W \
\max \left{dp(i-1, W), v_{i}+dp\left(i-1, W-w_{i}\right)\right} & \text { otherwise }
\end{array}\right.$
1 | public static int binarySearch(int[] arr, int start, int end, int target) { |
差分数组的主要适用场景是频繁对原始数组的某个区间的元素进行增减。
这里就需要差分数组的技巧,类似前缀和技巧构造的 prefix
数组,我们先对 nums
数组构造一个 diff
差分数组,diff[i]
就是 nums[i]
和 nums[i-1]
之差:
对于已知有n个元素的数列d,建立记录它每项与前一项差值的差分数组f:显然,f[1]=d[1]-0=d[1]
;对于整数i∈[2,n]
,我们让f[i]=d[i]-d[i-1]
。
1 | int[] diff = new int[nums.length]; |
1 | 构造差分数组: |
通过这个 diff
差分数组是可以反推出原始数组 nums
的,代码逻辑如下:
1 | int[] res = new int[diff.length]; |
这样构造差分数组 diff,就可以快速进行区间增减的操作,如果你想对区间 nums[i..j]
的元素全部加 3
,那么只需要让 diff[i] += 3
,然后再让 diff[j+1] -= 3
1 | nums: 8 5 9 6 1 |
1 | 给你两个整数数组 source 和 target ,长度都是 n 。还有一个数组 allowedSwaps ,其中每个 allowedSwaps[i] = [ai, bi] 表示你可以交换数组 source 中下标为 ai 和 bi(下标从 0 开始)的两个元素。注意,你可以按 任意 顺序 多次 交换一对特定下标指向的元素。 |
1 | class Solution { |
1 | 未知 整数数组 arr 由 n 个非负整数组成。 |
如果将一个数a和另一个数b做xor 得到结果c, 再 c xor b 就可以得到a
加法的逆运算是减法,异或的逆运算还是异或
$u=(x+y)⊕z$
$(u⊕z)-y=x$
1 | class Solution { |
1 | 给你链表的头节点 head 和一个整数 k 。 |
1 | /** |
tag:
缺失模块。
1、请确保node版本大于6.2
2、在博客根目录(注意不是yilia根目录)执行以下命令:
npm i hexo-generator-json-content --save
3、在根目录_config.yml里添加配置:
jsonContent: meta: false pages: false posts: title: true date: true path: true text: false raw: false content: false slug: false updated: false comments: false link: false permalink: false excerpt: false categories: false tags: true