
leetcode
文章平均质量分 92
ShenYounger
这个作者很懒,什么都没留下…
展开
-
加权随机采样
https://lotabout.me/2018/Weighted-Random-Sampling/具体文章在上面转载 2020-07-03 22:18:20 · 938 阅读 · 0 评论 -
耐心排序
看到leetcode题目300.Longest Increasing Subsequence的n*log(n)解法需要用到耐心排序的思想,在中文网页找了一大圈,发现很多叙述都是错误百出的。等看到这个youtube视频,才完全清楚https://www.youtube.com/watch?v=rqON9p_7Kx4&t=274s...原创 2020-05-08 11:29:55 · 465 阅读 · 0 评论 -
LeetCode刷题记录
1.124 Hard原创 2020-04-27 08:34:27 · 300 阅读 · 0 评论 -
LeetCode刷题感悟
1.二叉树有关的算法,算法的主题框架并不一定是纯粹的递归。比如LeetCode1305,其框架先是递归的,后来是一个归并排序。2.二叉搜索树一个很重要的特性就是:树中任何结点的左子树中所有结点的值均比该结点小,右子树中所有结点的值均比该结点大。对二叉搜索树进行中序遍历即得到一个递增排序的序列。检查一个树是否是二叉搜索树可以使用中序遍历,根据递增排序的序列生成二叉搜索树也可以使用中序遍历。往...原创 2020-04-26 12:05:00 · 276 阅读 · 0 评论 -
[NOT] 380. Insert Delete GetRandom O(1)
其实我的思路之前是对的,需要用dict和list,list的存在是为了方便随机选取元素。而dict的存在是为了方便删除和添加元素,在此需要注意的一点是dict和set内部都是用hashmap实现的。我之所以最后没能成功实现O(1)时间复杂度的算法要求,根源在于没能解决list删除元素的时间复杂度问题。我想了用dict的val保存key在list中的index。但是从dict中删除key是很...原创 2020-04-07 20:21:44 · 189 阅读 · 0 评论 -
[NOT]LeetCode 384. Shuffle an Array
这篇博文考察的主要是Fisher–Yates shuffle 洗牌算法。这种洗牌算法的精髓是可以原地洗牌。那为什么可以原地随机洗牌呢?根源在于可以把数组拆分成两部分,后面一部分是已经洗好的牌,前面一部分是待洗的牌。其算法为#伪代码中,将已经洗牌的牌放在数组后面,将待洗的牌放在数组前面-- To shuffle an array a of n elements (indices 0....原创 2020-04-07 14:46:41 · 184 阅读 · 0 评论 -
[NOT]LeetCode 395. Longest Substring with At Least K Repeating Characters
这道题目考察的是分而治之:找到所有在字符串中出现次数少于k次的字符,然后以这些字符作为split points,这样就把原始的字符串split成多个子串(分而)。再对这些子串分别治之。不过需要想明白的一点是,为什么可以把这些字符作为split points,根本原因在于这些字符不可能出现在我们最后想要的子串中。此外需要注意的一点是分而治之会形成递归树。如果是上面把字符串split成尽...原创 2020-04-06 19:05:57 · 182 阅读 · 0 评论 -
LeetCode 542
这道题目不难,主要用到的思想是BFS。重要的是理清思路。a.首先从0开始,搜索周围的未被check过的1,把这些1全部赋值为1,并设置状态为checked,把这些1进行保存。b.从上面保存的1开始搜索周围的未被check过的1,把这些1全部赋值为2,并设置状态为checked,把这些2进行保存。c.从上面保存的2开始搜索周围的未被check过的1,把这些1全部赋值为3,并设置状态为chec...原创 2020-01-15 23:39:55 · 351 阅读 · 0 评论 -
二分法找数组中第K小的数
方法是二分法,可以说是快速排序的一个变形。#include void swap(int*a , int* b) { int temp = *a; *a = *b; *b = temp;}int findkth(int arr[], int l, int h, int k) { int x = arr[h]; int i = l-1, j;原创 2015-06-17 11:59:55 · 1310 阅读 · 0 评论 -
递归形式的快速排序
递归形式的如下:#includevoid quicksort(int x[],int first,int last){ int pivot,j,temp,i; if(first pivot=first; i=first; j=last; while(i原创 2015-06-16 17:55:10 · 421 阅读 · 0 评论 -
尾调用与尾递归
尾调用(Tail Call)是函数式编程的一个重要概念,本文介绍它的含义和用法。一、什么是尾调用?尾调用的概念非常简单,一句话就能说清楚,就是指某个函数的最后一步是调用另一个函数。function f(x){ return g(x);}上面代码中,函数f的最后一步是调用函数g,这就叫尾调用。以下两种情况,都不属于尾调用。//转载 2015-06-17 11:22:14 · 3260 阅读 · 0 评论 -
位的与运算与取模
在查看维基百科网页关于Linear congruential generator的c和c++实现时,发现在c语言实现中,代码如下:[cpp] view plaincopyint rseed = 0; #define RAND_MAX ((1U return rseed = (rseed * 1103515245 + 12345)原创 2015-06-18 22:27:52 · 1860 阅读 · 0 评论 -
通过有偏概率0/1生成器,生成无偏概率0/1生成器
此题为算法导论第二版,习题5.1-3。原题如下:5.1-3 假设你希望以各1/2的概率输出0和1。你可以自由使用一个输出0或1的过程BIASED-RANDOM。它以概率p输出1,以概率1-p输出0,其中0 要求解此题,可以如下思索:既然我们要构建一个无偏过程,这个过程产生0和1的概率都是1/2,那么就要计算两个事件的概率,我们记这两个事件分别为A和B,其概率为p(A)和p(B)。之后我原创 2015-06-18 11:42:16 · 3379 阅读 · 1 评论 -
计算机中的原码、反码与补码
很久之前学习过的东西了,最近发现忘记,重新记录一下。1. 原码原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值. 比如如果是8位二进制:[+1]原 = 0000 0001[-1]原 = 1000 0001第一位是符号位. 因为第一位是符号位, 所以8位二进制数的取值范围就是:[1111 1111 , 0111原创 2015-06-18 22:44:07 · 887 阅读 · 0 评论 -
伪随机数生成器
在所有的编程语言中,基本上都会有产生伪随机数的库函数。长期以来,我一直很好奇,这些函数,究竟是如何产生伪随机数的。最近通过stack overflow和维基百科,我大概了解了一下伪随机数的生成过程。这篇文章的目的,并不是帮助大家了解很多伪随机算法的原理、效率、历史,也不是为了深入某一个或者某几个伪随机数算法。这篇文章的意义,在于帮助大家消除对于伪随机数生成过程某种程度上的好奇心。对于伪随机生成器更原创 2015-06-18 10:39:15 · 2416 阅读 · 2 评论 -
用位运算来代替乘法、除法以及取模
假设有两个数,A和B。B为2^n,期中n>=0,A>=0。则:要求A * B的话,则可使用要求A / B的话,则可使用>>操作符,A >> n。要求A % B的话,则可使用&操作符,A&(B-1)。如果A为负数的话,则未必成立。比如,当A为-1,B为2的时候,可知(-1)%2=-1,而-(1)&0=0。记住,当我们把乘法,除法及取模运算转化为位运算时,都要求A>=0。原创 2015-06-18 21:16:04 · 9581 阅读 · 3 评论 -
c及c++中的取模运算
首先看C++中两个涉及到模运算的操作:std::cout << (-7 % 3) << std::endl;std::cout 上述两个操作的结果分别为-1和1。为何会这样呢?首先引述下2011年的ISO标准:ISO14882:2011(e) 5.6-4: The binary / operator yields the quotient, and the binary原创 2015-06-18 22:34:48 · 4665 阅读 · 0 评论 -
5. Longest Palindromic Substring
求最长回文字符串是面试时候的经典问题。今天,介绍两种解法,第一种为二维的DP,时间,空间复杂度均为O(N^2)。第二种为更普遍的一种解法,时间复杂度为O(N^2),空间复杂度为O(1)。首先介绍二维DP,在做这道题的时候,我一开始就想用DP来做,但是当时只考虑到了一维DP,结果死活找不出递推方程。后来参考了别人的答案,才知道二维DP到底怎么做。在二维DP的时候,需要开辟一个二维数组,我发现当使用动原创 2015-06-21 20:57:23 · 353 阅读 · 0 评论 -
通过变量定义数组大小
目前的c++标准,支持VLA,也就是可以通过变量来定义数组的大小。比如:int size = 10;int arr[size] = {0};原创 2015-06-22 12:22:34 · 5249 阅读 · 1 评论 -
6. ZigZag Conversion
这道题目,我一开始的解法太过复杂,虽然勉强可以AC,但是调试和维护什么的,都很费精力。想想还是自己的算法不够好,虽然非常细致、精细,但是实现起来,却过于复杂,不够简单。我写的代码如下: string convert(string s, int numRows) { if (numRows == 1) { // 特殊情况 retur原创 2015-06-23 15:11:12 · 331 阅读 · 0 评论 -
数组的初始化
对于数组,初始化最普遍的方式为:int myArray[10]={5,5,5,5,5,5,5,5,5,5};那些只有缺失值的元素,将被初始化为0:int myArray[10] = { 1, 2 }; // initialize to 1,2,0,0,0...所以下列初始化式将初始化所有的元素为0:int my原创 2015-06-22 20:35:54 · 374 阅读 · 0 评论 -
9. Palindrome Number
在做这道题目的时候,一开始我的想法是如果输入的整数x为负数,则直接返回false,如果为非负数,则将x翻转,翻转后的数为after,如果after==x,则返回true,否则返回false。我这个算法的缺点和优点都很明显,优点是实现简单,逻辑便于理解。缺点是对于一些case,花费的时间可能会比较大,比如对于122222224,尽管我们可以很快就判断这个数不是回环数(因为起始数字为1,末尾数字为4)原创 2015-06-23 16:52:15 · 354 阅读 · 0 评论 -
7. Reverse Integer
算法本身并没有多少难度,难点是对于边界条件的判断,以及一些小的陷阱。具体需要注意的细节,我们写在代码注释中。#include using namespace std;class Solution {public: int reverse(int x) { long long tmp = x, result = 0; // 把t原创 2015-06-21 15:27:51 · 380 阅读 · 0 评论 -
int与long long之间的转换
今天看了下c++ primer,才知道假如a为long long或者double类型,b为int类型,假如有表达式a >= b,则编译器会将b先转化为long long或者double类型,也就是说会将窄类型自动转化为宽类型,这一步是自动转化的,没有必要在代码中再强制转化。但是有个特例,假如a = INT32_MIN,则-a会越界,其数值在我的平台上为-2147483648,如果要得到原创 2015-06-24 13:40:04 · 8415 阅读 · 0 评论 -
12. Integer to Roman
首先要解决这道题,你应该首先了解罗马数字。参见维基百科https://zh.wikipedia.org/wiki/%E7%BD%97%E9%A9%AC%E6%95%B0%E5%AD%97。罗马数字主要由7个字母来构成,不同的字母代表不同的十进制数值。I = 1;V = 5;X = 10;L = 50;C = 100;D = 500;M = 1000;这道题,我的解法原创 2015-06-29 15:17:31 · 351 阅读 · 0 评论 -
13. Roman to Integer
此道题目,跟第12题,恰好相反,要求从罗马数字转到阿拉伯数字。这道题,我的算法依然比较复杂,主要是因为对于题目内在的规律和整体的结构缺乏了解,所以以后一定要好好理顺题目的内在结构和题目的规律。这道题,我的算法基本上算是直接枚举,因为缺乏对于题目内在规律的洞察,所以很麻烦。我的代码如下: int romanToInt(string s) { int index = 0, i原创 2015-06-29 16:54:07 · 375 阅读 · 0 评论 -
14. Longest Common Prefix
这道题目比较常规和简单,我的算法是先计算出字符串数组中最短的那个字符串的长度maxCommLen,然后从后往前扫,变量cnt+1记录目前探测到的最长字符串的长度,如果遇到了一个非共同字符,则更新变量cnt。后来想了一下,这样写代码比较复杂,需要维护cnt这个变量,而且遍历次数会变多。参考了一下别人的代码,其实从前向后扫,更直观,效率也更好。无论是从后向前还是从前向后,时间复杂度都是O(N*M),其原创 2015-06-29 19:12:22 · 400 阅读 · 0 评论 -
16. 3Sum Closest
此题是3Sum的变体,不是特别难,当然前提是3Sum这样的问题,你很熟悉,这道题跟3Sum的主要区别是需要维护一个非负数min,其数值大小衡量找到的三个数的和与target相距的距离。在这里需要牢记这一类问题的解法:双指针从左和右同时向中间进行扫描。代码如下: int threeSumClosest(vector& nums, int target) { int min原创 2015-06-30 21:54:09 · 360 阅读 · 0 评论 -
15. 3Sum
这道题目,我的解法又是过于复杂了,用了map,而且把情形进行分类,结果搞得非常复杂。我的代码如下: vector getVec(int a, int b, int c) { vector result; int arr[] = {a, b, c}, tmp; for (int i=0; i<2; i++) { for原创 2015-06-30 16:58:14 · 274 阅读 · 0 评论 -
linux定时运行命令脚本——crontab
Linux中,周期执行的任务一般由cron这个守护进程来处理 ps -ef | grep cron cron读取一个或多个配置文件,这些配置文件中包含了命令行及其调用时间。cron的配置文件称为“crontab”,是“cron table”的简写。一、 cron在3个地方查找配置文件(设置shell脚本):1、/var/spool/cron/yanggang 这个转载 2015-06-30 19:17:37 · 369 阅读 · 0 评论 -
1. Two Sum
这道题,总的来说,共有两种解法。一种解法是双指针扫描,向中间进行夹逼。时间复杂度为O(nlogn)。但是为了保存下标,需要加个结构体,所以还是挺麻烦的,代码如下: vector twoSum(vector& nums, int target) { int len = (int)nums.size(), i, sum; vector result;原创 2015-06-30 20:14:38 · 333 阅读 · 0 评论 -
24. Swap Nodes in Pairs
此道题目是关于链表操作的。在算法中,我们主要操作三个指针,分别为p, p->next以及pre。其中p和p->next指向待交换的两个节点。pre指向p前面的那个节点。在代码中还需要注意的一点是,我们添加了一个头结点,这样之后的操作会更加方便。代码如下: ListNode *swapPairs(ListNode *head) { ListNode tmphead(0); tmphe原创 2015-07-08 17:39:24 · 333 阅读 · 0 评论 -
Reverse Nodes in k-Group
这道题目,我的解法思想与Swap Nodes in Pairs那道题基本上是一样的,只不过在翻转group内节点的时候,我使用了数组栈。我的代码如下: ListNode* reverseKGroup(ListNode* head, int k) { int cnt = 0; // 计数 ListNode *sstack[k], *cursor; // 数组原创 2015-07-08 19:20:12 · 345 阅读 · 0 评论 -
22. Generate Parentheses
这道题目,我是通过DFS来做的,但是为了判断由N个“(”和N个")"生成的字符串是否合法,于是我又写了个函数ifNormal。ifNormal函数的复杂度为为O(N)。而实际上,根本不需要另外写ifNormal函数。那怎么判断生成的字符串是否合法,或者从在程序逻辑上根本不允许生成那些不合法的字符串呢?答案就是在DFS的时候,如果"("的数量小于N,那么就可以继续放"(",如果")"的数量小于"("原创 2015-07-02 22:17:06 · 361 阅读 · 0 评论 -
19. Remove Nth Node From End of List
此道题目,我也只是遍历一次链表,但是因为使用了vector所以,空间复杂度为O(N),我的代码如下: ListNode* removeNthFromEnd(ListNode* head, int n) { vector pointers; // 存储指针 ListNode* tmp = head; while (tmp != NULL) {原创 2015-07-02 13:37:35 · 408 阅读 · 0 评论 -
17. Letter Combinations of a Phone Number
此道题目为经典的DFS题目,可以用DFS解决。很长时间没有写递归题目了,所以我的解法占用空间较大,比较高效的写法是只在栈中维护一个字符序列,而我的解法则是维护了3^N个字符序列,其中N为输入的digits的长度。我的代码如下: string d2S[10] = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz原创 2015-07-01 19:11:38 · 391 阅读 · 0 评论 -
C++ STL中常见容器的时间复杂度
map, set, multimap, and multiset上述四种容器采用红黑树实现,红黑树是平衡二叉树的一种。不同操作的时间复杂度近似为:插入: O(logN)查看:O(logN)删除:O(logN)hash_map, hash_set, hash_multimap, and hash_multiset上述四种容器采用哈希表实现,不同操作的时间复杂度为:原创 2015-07-02 10:44:40 · 48132 阅读 · 3 评论 -
21. Merge Two Sorted Lists
此道题目,我的解法还是略显复杂,原因是当一个链表指针为空,而另外一个链表还有元素时,为了串联余下的元素,我又遍历了一遍尚有元素的链表。这样就操作复杂了。我的解法如下: ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { if (!l1 && !l2) { return NUL原创 2015-07-02 15:21:14 · 339 阅读 · 0 评论 -
26. Remove Duplicates from Sorted Array
这道题目,我一开始以为要改变nums里面的元素,所以使用了vector的erase方法,所以运行时间较长,56ms。第一个版本,每次只erase一个元素,第二个版本,每次erase一段重复的元素。第一个版本的代码如下: int removeDuplicates(vector& nums) { if (nums.size() == 0) retu原创 2015-07-09 12:36:25 · 376 阅读 · 0 评论 -
在vector中通过下标删除元素
要删除单个元素,你应该这样做:std::vector vec;vec.push_back(6);vec.push_back(-17);vec.push_back(12);// 删除第二个元素 (vec[1])vec.erase(vec.begin() + 1);或者要一次性删除多个元素,你应该这样做:// 删除第二个和第三个元素 (vec[1], vec[2])ve原创 2015-07-09 12:44:23 · 41093 阅读 · 0 评论