单调递增的数字
方法:
代码
1 | class Solution: |
复杂度
时间复杂度:O(D)。其中 D≈logN,N 是数字的长度。 空间复杂度:O(D)。
1 | class Solution: |
时间复杂度:O(D)。其中 D≈logN,N 是数字的长度。 空间复杂度:O(D)。
维护一个递增栈,但当前元素小于栈顶元素,则移掉栈顶元素。
转自
作者:monkeybing 链接:https://leetcode-cn.com/problems/remove-k-digits/solution/cyu-yan-zhan-shi-xian-tan-xin-suan-fa-by-monkeybin/ 来源:力扣(LeetCode)
本题采用贪心思路:
举例来说:如果字符串num = "123456789", k = 3,我们只需要删除最后3个数字,得到"123456". 如果字符串num = "1432219", k = 3,需要从前到后遍历查找逆序数字,进行删除,第一个逆序数字为'4',第二个逆序数字为'3',第三个逆序数字为第二个'2',最后得到"1219"。
所以可以采用栈实现,每次遍历,判断如果栈非空,且当前数字大于栈顶数字,且k还有剩余(不为0),将栈顶数字出栈。最后将当前数字入栈。 如果遍历完成后,k仍有剩余,则依次将栈顶数字出栈。最后栈中保存的数字即为所求。按照从栈底到栈顶输出即可。 注意:特判场景,如果最后所有数字均出栈,即栈为空,需要返回"0"。
1 | class Solution: |
时间复杂度:O(n).
空间复杂度:O(n).
转自:
作者:labuladong 链接:https://leetcode-cn.com/problems/non-overlapping-intervals/solution/tan-xin-suan-fa-zhi-qu-jian-diao-du-wen-ti-by-labu/ 来源:力扣(LeetCode)
什么是贪心算法呢?贪心算法可以认为是动态规划算法的一个特例,相比动态规划,使用贪心算法需要满足更多的条件(贪心选择性质),但是效率比动态规划要高。
比如说一个算法问题使用暴力解法需要指数级时间,如果能使用动态规划消除重叠子问题,就可以降到多项式级别的时间,如果满足贪心选择性质,那么可以进一步降低时间复杂度,达到线性级别的。
什么是贪心选择性质呢,简单说就是:每一步都做出一个局部最优的选择,最终的结果就是全局最优。注意哦,这是一种特殊性质,其实只有一部分问题拥有这个性质。
比如你面前放着 100 张人民币,你只能拿十张,怎么才能拿最多的面额?显然每次选择剩下钞票中面值最大的一张,最后你的选择一定是最优的。
然而,大部分问题明显不具有贪心选择性质。比如打牌,对手出对儿三,按照贪心策略,你应该出尽可能小的牌刚好压制住对方,但现实情况我们甚至可能会出王炸。这种情况就不能用贪心算法,而得使用动态规划解决,参见前文动态规划解决博弈问题。
转自:
作者:labuladong 链接:https://leetcode-cn.com/problems/non-overlapping-intervals/solution/tan-xin-suan-fa-zhi-qu-jian-diao-du-wen-ti-by-labu/ 来源:力扣(LeetCode)
本文解决一个很经典的贪心算法问题 Interval
Scheduling(区间调度问题)。给你很多形如
[start, end]
的闭区间,请你设计一个算法,算出这些区间中最多有几个互不相交的区间。
举个例子,intvs = [[1,3], [2,4], [3,6]]
,这些区间最多有 2
个区间互不相交,即 [[1,3], [3,6]]
,你的算法应该返回
2。注意边界相同并不算相交。
这个问题在生活中的应用广泛,比如你今天有好几个活动,每个活动都可以用区间 [start, end] 表示开始和结束的时间,请问你今天最多能参加几个活动呢?显然你一个人不能同时参加两个活动,所以说这个问题就是求这些时间区间的最大不相交子集。
1 | class Solution { |
时间复杂度:O(nlogn). 排序需要O(nlogn)的时间。
空间复杂度:O(1). 不需要额外空间。
利用Python切片,对s中的每个字符,若在t中,下一步比较index+1开始的字符串
1 | class Solution: |
若相等,两个指针都往前移,若不等,快指针往前移。最后比较慢指针与s的长度。
1 | class Solution: |
遍历一遍数组,将元素装入HashSet,再从1开始,判断元素是否在HashSet中,若不存在,则该数为缺失的第一个正数。
时间复杂度:O(n).
空间复杂度:O(n).
1 | class Solution { |
通过预处理保证数组中的数全为正数,遍历数组,当读到数字 a 时,替换索引a 处元素的符号为负数。最后返回正数所对应的索引。
时间复杂度:O(n).所有的操作一共只会遍历长度为 N
的数组 4
次。
空间复杂度:O(1).只使用了常数的空间。
1 | class Solution { |
时间复杂度:O(nlog(n))。
空间复杂度:O(1) (or O(n)),在这里,我们对 nums 进行排序,因此内存大小是恒定的。如果我们不能修改输入数组,那么我们必须为 nums 的副本分配线性空间,并对其进行排序。
1 | class Solution { |
时间复杂度:O(n)
空间复杂度:O(n)
1 | class Solution { |
用序列[0,1,...,n]
的和减去给定的nums
的和,可得到缺失的数字。
时间复杂度:O(n)。
空间复杂度:O(1)。
1 | class Solution: |
高斯求和有溢出风险
先得到[0,1,...,n]
的异或值,再将结果对数组nums
中的每一个数进行一次异或运算,最终的异或结果即为这个缺失的数字。
在编写代码时,由于[0,1,...,n]
恰好是这个数组的下标加上
n,因此可以用一次循环完成所有的异或运算。
时间复杂度:O(n)。假设异或运算的时间复杂度是常数的。
空间复杂度:O(1)。
1 | class Solution: |
使用快慢指针找到中点,对链表前半部分进行翻转。
时间复杂度:O(n)
空间复杂度:O(1)
1 | /** |
时间复杂度:O(n). 每个节点只被访问了一次。
空间复杂度:最坏情况下栈内需要存放 O(h)个方法调用,其中 h是树的高度。由于 h∈O(n),可得出空间复杂度为 O(n)。
1 | /** |