LeetCode
Initial勿忘初心
生于忧患,死于安乐。
展开
-
19.Remove Nth Node From End of List
方法1:由于链表不能随机访问,所以很自然的想法是第一遍得到链表长度,然后计算倒数第n个结点的位置,但这样时间复杂度O(n2),想到用空间换取时间,可以用一个地址数组存储每个结点的地址,然后直接删除掉倒数第n个,返回头结点。 方法2:上面的方法虽然时间复杂度达到了线性,但是需要额外的空间,更好的方法是采用双指针追赶,设慢指针为pre,快指针为post,先让post指针走n步,然后pre指针开原创 2016-11-21 17:13:01 · 187 阅读 · 0 评论 -
53. Maximum Subarray Add to List QuestionEditorial Solution
假设最大子串为[i…k],那么其前缀之和sum[i…j](jsum[i…k],这与假设相反。得到这一结论,我们就可以设置一个临时变量用来计算前k个输之和,若为负,则将其置为0,否则判断其是否比当前最大值大。当k=n时,就找到了最大子串。class Solution {public: int maxSubArray(vector& nums) { int sum = nums[0];原创 2016-12-17 09:20:05 · 198 阅读 · 0 评论 -
120. Triangle
这道题很容易得出递推关系了,因为每个数只能由其上一层相邻的左右两个数走到,所以dp[i][k]=min(dp[i-1][k],dp[i-1][k+1])+triangle[i][k],由于我们只关心最小的数,所以其实可以直接用原来的数组存放中间值,到了最后一层中到达每个数的最小值的最小就是所求结果。class Solution {public: int minimumTotal(vecto原创 2016-12-17 09:19:04 · 167 阅读 · 0 评论 -
279. Perfect Squares Add to List QuestionEditorial Solution
典型的背包问题,假设小于n的完全平方数为Si,那么dp[n]=min(dp[n-S1],dp[n-S2],…dp[n-Si])+1class Solution {public: int numSquares(int n) { vectordp(n + 1, INT_MAX); dp[0]=0; dp[1] = 1; for (int i = 2; i < n + 1; ++原创 2016-12-17 09:17:20 · 387 阅读 · 0 评论 -
96. Unique Binary Search Trees
首先BST的定义为左子树每个结点小于根结点,右子树每个结点大于根节点。假设序列为[1…n],最大BST为dp[n],那么我们知道所有的BST为以每个数k(1 对于某个数k,以其为根的BST数量等于其左子树数量乘以右子树数量,现在讨论对于特定k,其左右子树数量。 左子树:左子树结点都小于k,很容易知道左子树的最大数量就为dp[k-1] 右子树:右子树结点大于k,即为[k…n],这里原创 2016-12-17 09:15:49 · 154 阅读 · 0 评论 -
377. Combination Sum IV
很标准的动态规划,容易得到递推公式dp(i)=dp(i-num[0])+dp(i-num[1])+......dp(i-num[n])。 也就是最后一个数字可以是数组中的任何一个小于target的数字,然后把所有的加起来 比如例子{1,2,3,4},则dp(4)=dp(0)+dp(1)+dp(2)+dp(3),分别为最后一步选择4,3,2,1,然后转化成了子问题 需要注意的原创 2016-11-22 19:45:19 · 157 阅读 · 0 评论 -
392. Is Subsequence
这套题直接依次比较字符就行了,相等就移动,如果s先移完,那说明是子串,如果t先移完,说明不是 class Solution {public: bool isSubsequence(string s, string t) { if (s.size() == 0) return 1; if (t.size() == 0) return 0; int j = s.siz原创 2016-11-22 19:01:35 · 180 阅读 · 0 评论 -
413. Arithmetic Slices
起初发现这道题很像子串问题,我们只需要求出每个连续的Slices的长度,然后计算每个连续Slices的子串个数即可。假设某个连续的串长度为N,那么它所包含的子串个数为(N-1)*(N-2)/2,很简单的数学问题 class Solution { public: int numberOfArithmeticSlices(vector& A) { if (A.size() < 3)原创 2016-11-22 18:31:09 · 248 阅读 · 0 评论 -
198. House Robber
动态规划,小偷有两种选择:1.偷最后一个房子,则倒数第二个房子不能再偷2.不偷最后一个房子所以问题可以简化为r[i]=max{r[i-1],r[i-2]+i}class Solution {public: int rob(vector& nums) { int n = nums.size(); if (n == 0) return 0; else原创 2016-11-21 19:28:41 · 297 阅读 · 0 评论 -
303. Range Sum Query - Immutable
动态规划问题,刚开始想直接写个二维数组,然后存下所有sum[i,j],后来发现测试案例有1W,然后RUN TIME ERROR了 后来发现其实只需要一维数组就可以解决,sum[i]存储i之前所有值的和,求解sum[i,j]=sum[j]-sum[i-1] 还有就是数组为空时返回0,感觉这个测试案例并没有什么卵用class NumArray {public:int*原创 2016-11-21 18:58:11 · 162 阅读 · 0 评论 -
204.count primes
思路: 这道题的核心是判断一个数是否为素数,但是如果利用最简单的将n以内的数遍历会超时。新的思路为那些素数的倍数的数为合数,所以可以将这些数排除,而对于一个素数p,只需要从p2开始排除,因为之前的数已经被更小的素数排除了。最后还有一点可以改进,就是p只需要判断到就可以了,以为此时p2已经大于n了。class Solution {public: int countPrime原创 2016-11-21 17:18:54 · 154 阅读 · 0 评论 -
406. Queue Reconstruction by Height
思路:这道题其实本质是一个排序问题,将pair元素排列,使得前面大于它的first元素的个数等于second。 思考一下很容易发现,对于那些height最低的元素,second就是他们的位置,所以可以直接先排列height最低的元素,排完之后会发现其实剩下的与之前类似,排第二低元素的时候只是有些位置被第一低元素占了,但是这并不影响什么,因为第二元素之前的空位置数必须为second才行,这原创 2016-11-21 17:22:08 · 193 阅读 · 0 评论 -
104. Maximum Depth of Binary Tree
思路:这道题很简单,利用递归定义,一棵树的高度等于左右子树高度较大的加1,对于空树或者只有一个节点的数,高度为1。/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; *原创 2016-11-21 17:20:39 · 151 阅读 · 0 评论 -
121.Best Time to Buy and Sell Stock
这道题的本质是求连续最大子区间问题,将数组中的每个元素转换为与前一位的差,那么最大的子区间就是收益最高的区间。 在求最大子区间时,可以想到,如果将区间分为两部分,那么最大子区间可能是左边区间的子区间,右边区间的子区间,也可能跨越中点的区间。对于左右子区间,可以很容易转化为递归步,所以只需要计算跨越中点的最大区间,这个很简单:从中点开始往左往右加,若更大,则更新区间端点,否则继续加。i原创 2016-11-21 17:17:00 · 282 阅读 · 0 评论 -
100.Same Tree
很简单的二叉树遍历问题,递归定义:两颗树相等=根相等+左子树相等+右子树相等。特殊处理根为空的情况,很容易写出递归的实现。非递归的话深度遍历使用栈,层次遍历使用队列。/** *Definition for a binary tree node. *struct TreeNode { * int val; * TreeNode *left; * Tree原创 2016-11-21 17:16:25 · 195 阅读 · 0 评论 -
70.Climbing Stairs
很经典的递归题,爬楼梯的方法=最后走1步+最后走2步,所以很容易就能写出递归算法。然而发现超时了,知道需要使用动态编程。其实上面的也是动态编程的思路,只不过动态编程将中间结果保存,这样其实遍历一次就能得到结果。现在重新思考了一下动态编程和分治的相同于区别:相同点:都需要寻找子问题,由子问题的解得到最终解不同点:分治可能除了子问题,还需要额外的操作,有时候额外的操作时间复杂度甚至超过了子原创 2016-11-21 17:15:50 · 190 阅读 · 0 评论 -
35.Search Insert Position
方法1:平凡思路从前往后比较,小于等于就停止,O(n)。方法2:在学习二分查找的时候知道二分查找不仅可以查找到元素是否存在,如果查找不到,那么停止的位置就是插入的位置。所以重新写一遍二分查找就好了,二分查找也有递归和非递归的,比较喜欢非递归,O(logn)。遍历法:class Solution {public: intsearchInsert(vector& num原创 2016-11-21 17:14:55 · 154 阅读 · 0 评论 -
21.Merge Two Sorted Lists
归并排序的归并步骤,只不过这里使用的是链表,但是归并并不需要随机访问,所以处理链表和数组的思路是一样的。设需要归并的两个链表分别为p,q(默认为升序排列),比较p和q最左边的元素大小,较小的向后移动,直到一个走到了链表末尾。将没有走完的链表接到已排好序的链表后面即可。/** *Definition for singly-linked list. *struct ListNode {原创 2016-11-21 17:13:58 · 217 阅读 · 0 评论 -
博客搬家至博客园
由于某些原因,现将博客搬家至博客园。CSDN博客不再更新。 欢迎大家访问我的新博客http://www.cnblogs.com/InitialD/原创 2017-08-12 09:48:05 · 313 阅读 · 0 评论