diff --git a/README.md b/README.md new file mode 100644 index 0000000..4984ac2 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# Cheat Sheet +slicing: nums[a,b]左闭右开,对应index: a到(b-1),对应1-based position: (a+1)到b + +range: range(a,b)左闭右开,表示a到b-1(所以nums[a,b]相当于用range(a,b)生成index a到(b-1), 然后调用index对应的position (a+1)到b) + +pandas.DataFrame: df[a:b] and df.iloc[a:b, :]都是左闭右开,取index: a到b-1的行 + +所以,只用记得code中的范围左闭右开后就是index范围,不要老想实际位置,只要记得位置等于index+1就行了 + +特例: +df.loc在slice时包含start和end +df.loc[2:5, :]表示index为2到5的行,所以左右都是闭区间 +而要回到iloc的范围的话就得使用df.loc[df.index[2:5], :],即先利用普通slice的左闭右开性质,取df.index中的2到4,强行去掉5 (df.index是一个RangeIndex data type) +note: 若非特殊说明,以上都是在讲index (start from 0) + +#48 +如果是顺时针旋转90度,transpose, then reverse order within each row (equivalently, 先reverse within each column再transpose) +如果是逆时针旋转90度,transpose, then reverse order within each column diff --git a/sort_by_leetcode/array/easy/121. Best Time to Buy and Sell Stock.py b/sort_by_leetcode/array/easy/121. Best Time to Buy and Sell Stock.py index 68dd361..a935185 100644 --- a/sort_by_leetcode/array/easy/121. Best Time to Buy and Sell Stock.py +++ b/sort_by_leetcode/array/easy/121. Best Time to Buy and Sell Stock.py @@ -24,8 +24,12 @@ def maxProfit(self, prices): :type prices: List[int] :rtype: int """ - curSum=maxSum=0 + curSum=maxSum=0 #可以连等,不错! for i in range(1,len(prices)): - curSum=max(0,curSum+prices[i]-prices[i-1]) + curSum=max(0,curSum+prices[i]-prices[i-1]) + #开始的条件是当前price比上一个起始点更低,即从上一个起始点开始累计的return<0,此时重新开始累计 maxSum = max(curSum,maxSum) - return maxSum \ No newline at end of file + #结束的条件是当前的累计return比储存的所有累计return都要高 + return maxSum + #这一类题目(对一个动作的起始点都要做决定)都可以通过在每个点做决定的方法来减少时间复杂度:每个点决定要不要开始/结束 + #节省时间复杂度,暴力解法是对起始点各做循环,复杂度O(n^2)。现在复杂度是O(n) diff --git a/sort_by_leetcode/array/easy/122. Best Time to Buy and Sell Stock II.py b/sort_by_leetcode/array/easy/122. Best Time to Buy and Sell Stock II.py index f122fef..6feb7ef 100644 --- a/sort_by_leetcode/array/easy/122. Best Time to Buy and Sell Stock II.py +++ b/sort_by_leetcode/array/easy/122. Best Time to Buy and Sell Stock II.py @@ -6,10 +6,11 @@ """ """这道题比较简单,因为没有买卖次数限制,也没有买卖时间限制,如果后面的股价比前面的大,我们就买卖""" +"""主要学习连加的快捷写法:sum(some_function_of_i for i in ...)""" class Solution(object): def maxProfit(self, prices): """ :type prices: List[int] :rtype: int """ - return sum(max(prices[i+1]-prices[i],0) for i in range(len(prices)-1)) \ No newline at end of file + return sum(max(prices[i+1]-prices[i],0) for i in range(len(prices)-1)) diff --git a/sort_by_leetcode/array/easy/167. Two Sum II - Input array is sorted.py b/sort_by_leetcode/array/easy/167. Two Sum II - Input array is sorted.py index d1e2d2a..4f44844 100644 --- a/sort_by_leetcode/array/easy/167. Two Sum II - Input array is sorted.py +++ b/sort_by_leetcode/array/easy/167. Two Sum II - Input array is sorted.py @@ -19,6 +19,19 @@ def twoSum(self, numbers, target): :type target: int :rtype: List[int] """ +#暴力解法是n^2的复杂度,这里无非是偷懒了,把第二层循环替换成找dictonary的key +#难点就在于dictionary的value是不能直接查找的,但我们把数值存在key里面就可以直接查找 +""" +其实这个答案的写法已经很花哨了,最质朴的写法是: + res = dict() + for i in range(0,len(numbers)): + res[numbers[i]] = i + for i in range(0,len(numbers)): + sub = target - numbers[i] + if sub in res.keys(): + return [res[sub]+1,i+1] +给出的最优解无非是把两个相似的循环结合在一起,又省了一些iteration,不过复杂度of the same magnitude +""" res = dict() for i in range(0,len(numbers)): sub = target - numbers[i] @@ -26,4 +39,4 @@ def twoSum(self, numbers, target): return [res[sub]+1,i+1] else: res[numbers[i]] = i - return [] \ No newline at end of file + return [] diff --git a/sort_by_leetcode/array/easy/169. Majority Element.py b/sort_by_leetcode/array/easy/169. Majority Element.py index 76d711e..f929086 100644 --- a/sort_by_leetcode/array/easy/169. Majority Element.py +++ b/sort_by_leetcode/array/easy/169. Majority Element.py @@ -11,32 +11,50 @@ """ -"""思路,因为出现次数最多的元素大于元素个数的一半,所以使用count和cand,设目标值为a -""" - +#暴力解法(n^2): class Solution(object): def majorityElement(self, nums): - """ - :type nums: List[int] - :rtype: int - """ - cand = nums[0] - count = 1 - for i in nums[1:]: - if count == 0: - cand, count = i, 1 - else: - if i == cand: - count = count + 1 - else: - count = count - 1 - return cand -"""一行的思路""" + majority_count = len(nums)//2 + for num in nums: + count = sum(1 for elem in nums if elem == num) + if count > majority_count: + return num +#这里可以学习对list里出现某个值的计数方法:count = sum(1 for i in nums if i==target) +#但这个解法暴力在sum(1 for ...)本身也是循环,所以复杂度是n^2. + +#巧思路(NlogN) +class Solution: + def majorityElement(self, nums): + nums.sort() + return nums[len(nums)//2] +#或者直接一行:return sorted(nums)[len(nums)//2] +#sort的时间复杂度是NlogN + +#Hash table解法(n): +from collections import Counter +class Solution: + def majorityElement(self, nums): + counts = Counter(nums) + return max(counts.keys(), key=counts.get) +''' +这里import了Counter函数,直接生成各个值的频度表,format是dictionary (Hash table) +max函数的key选项用于比大小的数字和return数字不同的情况,比如要比较x^2时就用 max(nums, key=lambda x: x**2) +counts.keys()表示要return的数字是ditionary keys种的一个(得有括号,否则只是个函数)。counts.get是个函数(没有括号),给出key对应的值 +也可以把函数用lambda写出来 max(counts.keys(), key=lambda x:counts[x]) +Counter和max都是n时间复杂度,所以总共时间复杂度也是n。 +''' + +#Boyer-Moore Voting Algorithm (n) class Solution(object): def majorityElement(self, nums): - """ - :type nums: List[int] - :rtype: int - """ - return sorted(nums)[len(nums)/2] \ No newline at end of file + candidate, count = nums[0], 0 + for num in nums: + if num == candidate: + count += 1 + elif count == 0: + candidate, count = num, 1 + else: + count -= 1 + return candidate + diff --git a/sort_by_leetcode/array/easy/189. Rotate Array.py b/sort_by_leetcode/array/easy/189. Rotate Array.py index a0d8166..5ecbf43 100644 --- a/sort_by_leetcode/array/easy/189. Rotate Array.py +++ b/sort_by_leetcode/array/easy/189. Rotate Array.py @@ -19,7 +19,12 @@ """ """直接拼接数组即可""" - +#就是左边变成n-k+1到n,右边变成1到n-k. +#注意slicing是左闭右开,同时index=position-1。所以写成nums[n-k:n]和nums[0:n-k].而0和n是起始index所以可以省略 +#rule of thumb 1: 如果想要slice positions [a,b], 写成nums[a-1:b], 里面个数是b-a+1.如果a-1=0或b=N可以省略,其中N是指len(nums) +#rule of thumb 2: 反过来,code中的nums[a:b]指的是positions[a+1,b], 里面个数是b-a.如果a省略了说明a=0,那就是positions[1,b],如果b省略了说明b=N,那就是[a+1,N] +#注意nums[N]不存在,但是nums[N-1:N]就是最后一个元素nums[N-1] +#不知道为什么LHS写成nums[:],直接用nums就可以了,别忘了还要写return nums class Solution(object): def rotate(self, nums, k): """ diff --git a/sort_by_leetcode/array/easy/217. Contains Duplicate.py b/sort_by_leetcode/array/easy/217. Contains Duplicate.py index 7ffa8a3..460d885 100644 --- a/sort_by_leetcode/array/easy/217. Contains Duplicate.py +++ b/sort_by_leetcode/array/easy/217. Contains Duplicate.py @@ -6,7 +6,8 @@ """ """利用hash table,别忘了判断空数组的情况.其实更麻烦""" - +#如果是暴力解法,会在loop over num的过程中再与过去的出现过的num进行比较,O(N^2). +#所以常用技巧就是把查找过去出现过的num的任务交给dict,num in dict的复杂度只O(1).所以总的复杂度只有O(N) class Solution(object): def containsDuplicate(self, nums): """ @@ -15,19 +16,19 @@ def containsDuplicate(self, nums): """ if not nums: return False - dic = dict() + dic = dict() #建立空dict的方法: dict() for num in nums: if num in dic: - return True - dic[num] = 1 + return True #一旦出现return,整个def直接结束(不只是loop结束) + dic[num] = 1 #if num in dic的in函数判断的是keys而不是dic中的values,所以直接用当前num作为key,value就随便(比如1) return False """直接利用set的性质反而更简单""" - +#set()提取nums中的distinct values生成一个set. 原因很简单:set这种data type不能包含重复元素 class Solution(object): def containsDuplicate(self, nums): """ :type nums: List[int] :rtype: bool """ - return len(nums) != len(set(nums)) \ No newline at end of file + return len(nums) != len(set(nums)) diff --git a/sort_by_leetcode/array/easy/219. Contains Duplicate II.py b/sort_by_leetcode/array/easy/219. Contains Duplicate II.py index 9d3f675..4e90c31 100644 --- a/sort_by_leetcode/array/easy/219. Contains Duplicate II.py +++ b/sort_by_leetcode/array/easy/219. Contains Duplicate II.py @@ -4,6 +4,12 @@ """ """仍然用dict保存数组元素出现的位置,两种情况下更新""" +#和217一样,无非在判断num in dic时多加一个条件:index - dic[num] <= k,以及在dict中的value不能乱写了,得用nums的index +#for i in nums: 返回list values +#for i,value in enumerate(nums): 返回nums的 (index,value) pair +#for i in dic: 返回dictionary keys, 相当于for i in dic.keys() +#for i in dic.values(): 返回dictionary values +#for i,value in dic.items(): 返回dictionary的 (key,value) pair class Solution(object): def containsNearbyDuplicate(self, nums, k): """ @@ -12,8 +18,8 @@ def containsNearbyDuplicate(self, nums, k): :rtype: bool """ dic = dict() - for index,value in enumerate(nums): + for index,value in enumerate(nums): if value in dic and index - dic[value] <= k: return True dic[value] = index - return False \ No newline at end of file + return False diff --git a/sort_by_leetcode/array/easy/26. Remove Duplicates from Sorted Array.py b/sort_by_leetcode/array/easy/26. Remove Duplicates from Sorted Array.py index 12e3617..72a13ca 100644 --- a/sort_by_leetcode/array/easy/26. Remove Duplicates from Sorted Array.py +++ b/sort_by_leetcode/array/easy/26. Remove Duplicates from Sorted Array.py @@ -14,7 +14,11 @@ """ """题目要点:返回不重复数的个数,同时要排在数组的前面n个""" - +#loop over i in range(len(nums)) +#如果num[i]和第一个num相同就跳过,如果不同就留下replace第二个num (index=1, replacenums[1]),进入下一个i; +#... +#如果num[i]和上一个num相同就跳过,如果不同就留下replace上一个num的后面那一个 (index=index+1并replace nums[index]),进入下一个i; +#因为i的增速>=index的增速,所以replace nums[index]不会影响之后对nums[i]的比较 class Solution(object): def removeDuplicates(self, nums): """ @@ -29,4 +33,4 @@ def removeDuplicates(self, nums): index = index + 1 nums[index] = nums[i] - return index + 1 \ No newline at end of file + return index + 1 diff --git a/sort_by_leetcode/array/easy/268. Missing Number.py b/sort_by_leetcode/array/easy/268. Missing Number.py index 825169f..9a0f76f 100644 --- a/sort_by_leetcode/array/easy/268. Missing Number.py +++ b/sort_by_leetcode/array/easy/268. Missing Number.py @@ -6,9 +6,18 @@ Note: Your algorithm should run in linear runtime complexity. Could you implement it using only constant extra space complexity? - """ -"""利用求和公式求解""" + +#brute force, O(N) +class Solution(object): + def missingNumber(self, nums): + nums.sort() + for i,num in enumerate(nums): + if num != i: + return num + + +"""利用求和公式求解, O(1)""" class Solution(object): def missingNumber(self, nums): """ @@ -16,4 +25,4 @@ def missingNumber(self, nums): :rtype: int """ n = len(nums) - return n * (n+1) / 2 - sum(nums) \ No newline at end of file + return n * (n+1) / 2 - sum(nums) #一个list求和很方便:sum(nums) diff --git a/sort_by_leetcode/array/easy/27. Remove Element.py b/sort_by_leetcode/array/easy/27. Remove Element.py index 70c7c01..20838cf 100644 --- a/sort_by_leetcode/array/easy/27. Remove Element.py +++ b/sort_by_leetcode/array/easy/27. Remove Element.py @@ -18,6 +18,23 @@ """类似于26题的思路,要点是要把不等于目标值的元素放到数组前面 时间复杂度O(n) """ +#again, 之所以可以不用管i,直接替换index对应的值是因为:index <= i总是成立,所以改变nums[index]不影响下一轮对nums[i+1]的比较 +class Solution(object): + def removeElement(self, nums, val): + """ + :type nums: List[int] + :type val: int + :rtype: int + """ + index = 0 + for i in range(len(nums)): + if nums[i] != val: + nums[index] = nums[i] + index += 1 + return index + + + class Solution(object): def removeElement(self, nums, val): """ @@ -30,4 +47,4 @@ def removeElement(self, nums, val): if nums[i] != val: nums[index] = nums[i] index = index + 1 - return index \ No newline at end of file + return index