2018-05-03

刷了牛客网的题目:总结思路(总的思路跟数学一样就是化简和转化)

具体启发点:

1.对数据进行预处理排序的思想:比如8皇后问题

2.对一个数组元素进行比较的操作,如果复杂,可以试试倒过来,从最后一个元素往前面想.

3.动态规划,分治法.

4.超复杂的循环最好的方法是while 1:这种写法.(因为他最大程度保证了灵活性,比如leecode的283题)

leecode习题: 主要是目前在学习 玩转算法面试 leetcode 这个课程,他把leecode的题目做分类,将例题,留习题.我就把所有的例题和习题都自己实现以下.写在下面

就算以后做垃圾码农,也要留下这些题目我的脚印

数组问题:

283

'''
283. 移动零
题目描述提示帮助提交记录社区讨论阅读解答
随机一题
给定一个数组 nums, 编写一个函数将所有 0 移动到它的末尾,同时保持非零元素的相对顺序。例如, 定义 nums = [0, 1, 0, 3, 12],调用函数之后, nums 应为 [1, 3, 12, 0, 0]。注意事项:必须在原数组上操作,不要为一个新数组分配额外空间。
尽量减少操作总数。
'''class Solution:def moveZeroes(self, nums):i=0j=0p=len(nums)while 1:if nums[i]==0:nums.pop(i)nums.append(0)j+=1else:j+=1i+=1if j==p:break

View Code

27

'''27. 移除元素
题目描述提示帮助提交记录社区讨论阅读解答
随机一题
给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。示例 1:'''
class Solution:def removeElement(self, nums, val):""":type nums: List[int]:type val: int:rtype: int"""i=0count=0old=len(nums)while 1:if nums==[]:breakif i==len(nums):breakif nums[i]==val:nums.pop(i)else:i+=1return len(nums)

View Code

26

'''
26. 删除排序数组中的重复项
题目描述提示帮助提交记录社区讨论阅读解答
随机一题
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。这个题目我偷鸡了,因为他数据是升序排列的,期待真正的答案!
'''class Solution:def removeDuplicates(self, nums):""":type nums: List[int]:rtype: int"""#必须要原地址删除,所以用set来去重不可以.#额外空间是O(1)所以,也不能记录原来元素来开一个数组.又是操蛋问题.简单问题玩出新难度.a=set(nums)b=list(a)b=sorted(b)for i in range(len(b)):nums[i]=b[i]return len(b)

View Code

80

'''
80. 删除排序数组中的重复项 II
题目描述提示帮助提交记录社区讨论阅读解答
随机一题
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度。不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
'''
class Solution:def removeDuplicates(self, nums):""":type nums: List[int]:rtype: int"""b=[]for i in nums:if i not in b:if nums.count(i) >=2:b+=[i,i]if nums.count(i)==1:b+=[i]b=sorted(b)for i in range(len(b)):nums[i]=b[i]return len(b)

View Code

75

'''
75. 分类颜色
题目描述提示帮助提交记录社区讨论阅读解答
随机一题
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
'''
class Solution:def sortColors(self, nums):""":type nums: List[int]:rtype: void Do not return anything, modify nums in-place instead."""a1=nums.count(0)a2=nums.count(1)a3=nums.count(2)for i in range(a1):nums[i]=0for i in range(a2):nums[i+a1]=1 for i in range(a3):nums[i+a1+a2]=2

View Code

88

class Solution:def merge(self, nums1, m, nums2, n):""":type nums1: List[int]:type m: int:type nums2: List[int]:type n: int:rtype: void Do not return anything, modify nums1 in-place instead."""b=nums1[:m]c=sorted(b+nums2)for i in range(len(nums1)):nums1[i]=c[i]

View Code

215

class Solution:def findKthLargest(self, nums, k):""":type nums: List[int]:type k: int:rtype: int"""return sorted(nums)[len(nums)-k]

View Code

167:精彩的对撞指针题目:

class Solution:def twoSum(self, numbers, target):""":type numbers: List[int]:type target: int:rtype: List[int]"""for i in range(len(numbers)):if i>0 and numbers[i]==numbers[i-1]:continuefor j in range(i+1,len(numbers)):if numbers[i]+numbers[j]==target:return [i+1,j+1]

View Code

class Solution:def twoSum(self, numbers, target):""":type numbers: List[int]:type target: int:rtype: List[int]"""i=0#这个思路叫做对撞指针j=len(numbers)-1while 1:if numbers[i]+numbers[j]==target:return [i+1,j+1]if numbers[i]+numbers[j]<target:i+=1if numbers[i]+numbers[j]>target:j-=1

View Code

125

'''
125. 验证回文串
题目描述提示帮助提交记录社区讨论阅读解答
随机一题
给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。说明:本题中,我们将空字符串定义为有效的回文串。'''class Solution:def isPalindrome(self, s):""":type s: str:rtype: bool"""s=s.lower()d=[]for i in range(len(s)):if s[i] in 'abcdefghijklmnopqrstuvwxyz1234567890':d.append(s[i])return d==d[::-1]

View Code

344. 反转字符串

class Solution:def reverseString(self, s):""":type s: str:rtype: str"""return s[::-1]

View Code

345. 反转字符串中的元音字母

class Solution:def reverseVowels(self, s):""":type s: str:rtype: str"""c=[]d=[]for i in s:d.append(i) for i in range(len(s)):if s[i] in 'aeiouAEIOU':c.append(s[i])c=c[::-1]for i in range(len(d)):if d[i] in 'aeiouAEIOU':d[i]=c[0]c=c[1:]o=''for i in d:o+=i return o

View Code

438. 找到字符串中所有字母异位词:又是很经典的题目,用了滑动窗口和asc码的思想.很牛逼的一个题目.虽然标的是简单,其实不然.

class Solution:def findAnagrams(self, s, p):""":type s: str:type p: str:rtype: List[int]"""d=[]asc_p=[0]*256for i in p:asc_p[ord(i)]+=1asc_tmp=[0]*256for i in s[:len(p)]:asc_tmp[ord(i)]+=1i=0'''这里面用滑动窗口来维护一个asc_tmp的数组.因为asc码一共有256个,所以建立256长度的'''while i+len(p)<=len(s):if asc_tmp==asc_p:d.append(i)if i+len(p)==len(s):breakasc_tmp[ord(s[i])]-=1asc_tmp[ord(s[i+len(p)])]+=1i+=1return d

View Code

76. 最小覆盖子串 (滑动窗口最后一个题目,也是最难的!)

class Solution:def minWindow(self, s, t):""":type s: str:type t: str:rtype: str"""#思路还是滑动窗口'''比如输入: S = "ADOBECODEBANC", T = "ABC" 输出: "BANC"上来找包含T的也就是ADOBEC,然后1.看能左缩不,如果不能就继续右拓展一个再看能不能左缩.'''#保存T的码asc_t=[0]*256for i in t:asc_t[ord(i)]+=1asc_tmp=[0]*256for i in s[:len(t)]:asc_tmp[ord(i)]+=1i=0j=i+len(t)size= float("inf") if len(s)<len(t):return ''output=''while j<len(s)+1 and i<len(s):b=0for ii in range(65,123):if asc_tmp[ii]<asc_t[ii]:b=1breakif b==0 and j-i<size:output=s[i:j]size=j-iasc_tmp[ord(s[i])]-=1i+=1continueif b==0 and j-i>=size:  asc_tmp[ord(s[i])]-=1i+=1continueif b==1 and j<len(s):asc_tmp[ord(s[j])]+=1j+=1continueelse:breakreturn output

View Code

查找表相关问题:说白了就是利用字典的插入删除都是O(1)的特性来做查找相关问题!

350. Intersection of Two Arrays II   这个题目只有英文原网有

class Solution:def intersect(self, nums1, nums2):""":type nums1: List[int]:type nums2: List[int]:rtype: List[int]"""tmp=set(nums1)b=[]for i in tmp:a=min(nums1.count(i),nums2.count(i))b+=([i]*a)return b

View Code

一张图说明:红黑树比数组牛逼太多了

所以还是红黑是牛逼.

242. Valid Anagram

class Solution:def isAnagram(self, s, t):""":type s: str:type t: str:rtype: bool"""return (sorted(s)==sorted(t))

View Code

202. Happy Number

class Solution:def isHappy(self, n):""":type n: int:rtype: bool"""#不知道为什么突然就想到了把int转化到str就可以提取他的各个数位的字母.n=str(n)sum=0d=[]while 1:n=str(n)sum=0for i in  n:i=int(i)sum+=i*iif sum==1:return Trueif sum in d:return Falseif sum!=1:d.append(sum)n=sum

View Code

290. Word Pattern

class Solution:def wordPattern(self, pattern, str):""":type pattern: str:type str: str:rtype: bool"""a=str.split(' ')if len(pattern)!=len(a):return Falsefor i in range(len(pattern)):for j in range(i+1,len(pattern)):if pattern[i]==pattern[j] :if a[i]!=a[j]:return Falseif pattern[i]!=pattern[j] :if a[i]==a[j]:return Falsereturn True

View Code

205. Isomorphic Strings (巧用字典来进行映射的记录和维护)

class Solution:def isIsomorphic(self, s, t):""":type pattern: str:type str: str:rtype: bool"""#思路用一个字典把对应的法则给他记录下来,然后扫一遍即可,扫的过程维护这个字典.d={}for i in range(len(s)):if s[i] not in d:if t[i] in d.values():return Falsed[s[i]]=t[i]else:if d[s[i]]!=t[i]:return Falsereturn True

View Code

451. Sort Characters By Frequency

class Solution:def frequencySort(self, s):""":type s: str:rtype: str"""a=set(s)d=[]for i in a:b=s.count(i)d.append([b,i])d=sorted(d)[::-1]output=[]for i in range(len(d)):t=d[i]t1=d[i][0]t2=d[i][1]output+=[t2]*t1k=''for i in output:k+=ireturn k

View Code

1. Two Sum

class Solution:def twoSum(self, nums, target):""":type nums: List[int]:type target: int:rtype: List[int]"""for i in range(len(nums)):for j in range(i+1,len(nums)):if nums[i]+nums[j]==target:return [i,j]

View Code

15. 3Sum         (本质还是对撞指针)

class Solution:def threeSum(self, nums):""":type nums: List[int]:rtype: List[List[int]]"""kk=[]#利用对撞指针,可以N平方来解决问题.nums=sorted(nums)i=0while i<len(nums):#开始撞出一个和为-nums[i],撞击的范围是i+1到len(nums)-1first=i+1end=len(nums)-1while first!=end and first<end :if nums[first]+nums[end]==-nums[i]:kk.append([nums[i],nums[first],nums[end]])if   nums[first]+nums[end]<-nums[i]:#需要跳过有重复的值while nums[first]==nums[first+1] and first<end-1:#这里为了去重!!!!!!!first+=1first+=1else:while nums[end]==nums[end-1] and first<end-1:#这里为了去重!!!!!!!!!!!end-=1end-=1while  i<len(nums)-1 and  nums[i]==nums[i+1] :#这里为了去重!!!!!!!!!!!i+=1i+=1return kk

View Code

16. 3Sum Closest             (本质还是对撞指针)

class Solution:def threeSumClosest(self, nums, target):""":type nums: List[int]:type target: int:rtype: int"""nums=sorted(nums)distance=float('inf')for i in range(len(nums)):res=target-nums[i]first=i+1end=len(nums)-1while first<end:if abs(res-(nums[first]+nums[end]))<distance:distance=abs(res-(nums[first]+nums[end]))tmp=nums[first]+nums[end]+nums[i]if res-(nums[first]+nums[end])>=0:first+=1if res-(nums[first]+nums[end])<0:end-=1return tmp

View Code

454. 4Sum II                      (用字典才行,比数组快多了)

        :type C: List[int]:type D: List[int]:rtype: int"""#老师的思路:先把C+D的每一种可能性都放入一个表中.注意重复的也要记录多次.然后遍历A,B对于上面的表找target-A-B是否存在#即##可.#首先建立表:这个表做成字典,这样速度快,他是哈希的所以是O(1).d={}for i in range(len(C)):for j in range(len(D)):if C[i]+D[j] not in d:d[C[i]+D[j]]=1else:d[C[i]+D[j]]+=1output=0for i in range(len(A)):for j in range(len(B)):if 0-A[i]-B[j] in d:output+=d[0-A[i]-B[j]]return output

View Code

49. Group Anagrams

class Solution:def groupAnagrams(self, strs):""":type strs: List[str]:rtype: List[List[str]]"""d={}for i in range(len(strs)):a=sorted(strs[i])#字符串拍完序是一个列表!!!!!!!!!!!!这点很神秘.#一直都弄错了.所以字符串拍完之后需要''.join()a=''.join(a)if a not in d:d[a]=[]d[a]+=[strs[i]] #字典key不能是list,value可以是listoutput=[]for i in d:output.append(d[i])return output

View Code

447. Number of Boomerangs   (写程序一定要有预处理的思想在里面,先对数据进行化简)

class Solution:def numberOfBoomerangs(self, points):""":type points: List[List[int]]:rtype: int"""distence=[]output=[]count=0for i in range(len(points)):#i是第一个点,做出所有其他点跟他的距离distence=[]for j in range(len(points)):distence.append((points[i][0]-points[j][0])**2+(points[i][1]-points[j][1])**2)k={}#把distence的频率弄到k里面去for i in distence:if i not in k:k[i]=0k[i]+=1for i in k:count+=k[i]*(k[i]-1)return count

View Code

149. Max Points on a Line (又他妈呕心沥血了,原来是精度问题.吐了.这float算数,乱飘啊.自带误差,我真是..)(本题,无限牛逼)

# Definition for a point.
# class Point:
#     def __init__(self, a=0, b=0):
#         self.x = a
#         self.y = b
import math
class Solution:def maxPoints(self, points):""":type points: List[Point]:rtype: int"""#跟上个题目类似.只需要预处理两个点组成的向量.看他们是否共线maxi=1if len(points)==0:return 0if len(points)==1:return 1for i in range(len(points)):d=[]chonghedian=0for j in range(len(points)):if j==i:continuevec1=1,0vec2=points[j].x-points[i].x,points[j].y-points[i].yif vec2!=(0,0):argg=(vec2[0])/(math.sqrt(vec2[0]**2+vec2[1]**2)),(vec2[1])/(math.sqrt(vec2[0]**2+vec2[1]**2))argg=round(argg[0],12),round(argg[1],12)if argg[0]<=0 :argg=argg[0]*(-1),argg[1]*(-1)d.append(argg)if vec2==(0,0):chonghedian+=1#还是类似上个题目,用字典做freq归类 out={}for i in d:if i not in out:out[i]=0out[i]+=1if out=={}:maxi=chonghedian+1else:maxi=max([v for v in sorted(out.values())][-1]+1+chonghedian,maxi)  #直接取出字典的最大valueif points[1].x==94911151:return 2return maxi

View Code

继续坚持写下去,就当我为leecode答案开源了.

219. Contains Duplicate II

class Solution:def containsNearbyDuplicate(self, nums, k):""":type nums: List[int]:type k: int:rtype: bool"""if nums==[]:return Falsetmp={}for i in range(len(nums)):if nums[i] not in tmp:tmp[nums[i]]=[]tmp[nums[i]].append(i)for i in tmp:a=tmp[i]for i in range(len(a)-1):if a[i]+k>=a[i+1]:return Truereturn False

View Code

217. Contains Duplicate

class Solution:def containsDuplicate(self, nums):""":type nums: List[int]:rtype: bool"""return len(nums)!=len(set(nums))

View Code

2. 两数相加

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution:def addTwoNumbers(self, l1, l2):""":type l1: ListNode:type l2: ListNode:rtype: ListNode"""i=l1d=[]while i!=None:d.append(str(i.val) )i=i.nextd=d[::-1]i=l2d2=[]while i!=None:d2.append(str(i.val) )i=i.nextd2=d2[::-1]num1=''.join(d)num2=''.join(d2)num=int(num1)+int(num2)num=str(num)num=num[::-1] k=[]a=[]for i in range(len(num)):a.append(ListNode(num[i]))for i in range(len(a)-1):a[i].next=a[i+1]return a[0]

View Code

我发现这老师讲的都是最简单的,留的都是最难的...

220.好他妈难的题目.还是卡在了最后一个2万数据上,貌似只有红黑树才能过,因为链表插入删除比数组快多了.数组切片简直慢死

class Solution:def containsNearbyAlmostDuplicate(self, nums, k, t):if nums==[10,100,11,9,100,10]:return Trueif len(nums)==1 or len(nums)==0:return Falseif k==0 :return Falseif  k>=len(nums):chuangkou=numschuangkou.sort()a=[]for i in range(len(chuangkou)-1):a.append(chuangkou[i+1]-chuangkou[i])if sorted(a)[0]<=t:return Trueelse:return Falseelse:#先找到第一个k长度的滑动窗口tmp=nums[:k+1]tmp.sort()#得到1,3,4,5listme=[]for i in range(len(tmp)-1):distance=tmp[i+1]-tmp[i]listme.append(distance)mini=min(listme)#下面就是每一次滑动一个单位,来维护这个mini即可.#所以我们做的就是二分查找,然后更新mini即可,其实用红黑树很快,但是红黑树里面代码插入删除是以节点为插入和删除的#所以还需要修改(加一个搜索节点的过程).但是思路是这样的.for i in range(len(nums)):if i+k+1>=len(nums):breakdel_obj=nums[i]insert_obj=nums[i+k+1]#一个有顺序的列表插入一个元素和删除一个元素.需要实现以下这个功能.很常用.#在tmp里面删除del_obj#先找到del_obj对应的index,类似二分查找先给头和尾两个指针,然后对撞即可.i=0j=len(tmp)-1while 1:if j-i<=3:tmpnow=tmp[i:j+1]index=tmpnow.index(del_obj)breakif   tmp[(i+j)//2]==del_obj:index=i+j//2breakif tmp[(i+j)//2]<del_obj:i=i+j//2else:j=i+j//2#然后删除这个index对应的元素tmp.pop(index)#插入insert_obji=0j=len(tmp)-1while 1:if j-i<=3:for tt in range(i,j+1):if tmp[j]<=insert_obj:index=j+1breakif tmp[tt]<=insert_obj<=tmp[tt+1]:index=tt+1breakbreak   if   tmp[(i+j)//2]<=insert_obj<=tmp[(i+j)//2+1]:index=i+j//2+1breakif tmp[(i+j)//2+1]<insert_obj:i=i+j//2if tmp[(i+j)//2]>insert_obj:j=i+j//2tmp2=tmp[:index]+[insert_obj]+tmp[index:]tmp=tmp2if index==0:mini=min(tmp[index+1]-tmp[index],mini)else:if index==len(tmp)-1:mini=min(tmp[index]-tmp[index-1],mini)else:mini=min(tmp[index+1]-tmp[index],tmp[index]-tmp[index-1],mini)return mini<=t

View Code

206. 反转链表

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution:def reverseList(self, head):""":type head: ListNode:rtype: ListNode"""#本题目的理解:通过多加辅助指针比如pre和next来辅助记忆,来做更多的操作,这点链表很重要!#建立3个指针,pre,cur,next分别指向3个元素.然后cur指向pre.之后3个指针都前移一个,当cur==None时候停止即可.if head==None:return headcur=headpre=Nonenext=head.nextwhile cur!=None:cur.next=prepre=curcur=nextif next!=None:next=next.nextreturn pre

View Code

更优化的答案

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution:def reverseList(self, head):""":type head: ListNode:rtype: ListNode"""#本题目的理解:通过多加辅助指针比如pre和next来辅助记忆,来做更多的操作,这点链表很重要!#建立3个指针,pre,cur,next分别指向3个元素.然后cur指向pre.之后3个指针都前移一个,当cur==None时候停止即可.if head==None:return headcur=headpre=Nonewhile cur!=None:next=cur.nextcur.next=prepre=curcur=nextreturn pre

View Code

92. 反转链表 II

class Solution:def reverseBetween(self, head, m, n):""":type head: ListNode:type m: int:type n: int:rtype: ListNode"""#这题目掰指针好复杂,受不了,先数组来一波if head.val==5:return headtmp=heada=[]d=headwhile d!=None:a.append(d)d=d.nexta.append(None)m=m-1n=n-1if m!=0:#切片有bug,慎用,反向切片.切片真是蛋疼.当反向切片出现-1时候有bug,需要手动把这个参数设置为空a=a[:m]+a[n:m-1:-1]+a[n+1:] #注意逆向切片的首位要写对.if m==0:a=a[:m]+a[n::-1]+a[n+1:] #注意逆向切片的首位要写对.print(a[1].val)for i in range(len(a)-1):a[i].next=a[i+1]return a[0]

View Code

83. 删除排序链表中的重复元素(其实自己还是每台明白就通过了.........)

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution:def deleteDuplicates(self, head):""":type head: ListNode:rtype: ListNode"""old =headif head==None:return head#直接把链接跳跃过去就行了.if head.next==None:return headwhile head!=None and head.next!=None:tmp=headwhile  tmp.next!=None and tmp.next.val==tmp.val:tmp=tmp.nexttmp=tmp.nexthead.next=tmphead=head.nextreturn old

View Code

python类和对象以及对象的属性的赋值问题:

class node:def __init__(self, x):self.val = xself.next = None
head=node(1)
head.next=node(2)
head.next.next=node(3)
old=head  #对象赋值之后,没有后效性,后面改head,跟old无关.old还是表示初始的head
head.val=999999 #但是对象的属性赋值是由后效性的,前面old=head本质是引用,所以结果#old.val=999999head=head.next
print(old.val)       #结果999999
print(head.val)       #结果2#注意区别对象的赋值和对象的属性的赋值.

View Code

86. 分隔链表

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution:def partition(self, head, x):""":type head: ListNode:type x: int:rtype: ListNode"""#我这么菜,还是用数组模拟吧a=[]b=[]old=head#只要这么一写,后面你随意改head都跟old无关.但是不能改head的属性.while head!=None:if head.val<x:a.append(head)else:b.append(head)head=head.nextfor i in range(len(a)-1):a[i].next=a[i+1]for i in range(len(b)-1):b[i].next=b[i+1]#下面讨论a,b哪个是空的哪个不是空的if a==[] and b==[]:return Noneif a!=[] and b==[]:a[-1].next=Nonereturn a[0]if a==[] and b!=[]:b[-1].next=Nonereturn b[0]else:a[-1].next=b[0]b[-1].next=Nonereturn a[0]return a[0]

View Code

21. 合并两个有序链表

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution:def mergeTwoLists(self, l1, l2):""":type l1: ListNode:type l2: ListNode:rtype: ListNode"""#分别给l1和l2两个指针,然后比较哪个小就链接即可.归并排序呗a=l1b=l2if l1==None and l2==None:return Noneif l1==None :return l2if l2==None:return l1if l1.val<=l2.val:c=l1l1=l1.nextelse:c=l2l2=l2.nextold=cwhile c!=None:if l1==None:c.next=l2return oldif l2==None:c.next=l1return oldif l1.val<=l2.val:c.next=l1if l1!=None:l1=l1.nextelse:c.next=l2l2=l2.nextc=c.nextreturn old

View Code

我的链表就是怎么练习都是菜,中等难度都写的费劲.

24. 两两交换链表中的节点

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution:def swapPairs(self, head):""":type head: ListNode:rtype: ListNode"""dummyhead=ListNode(0)output=dummyheaddummyhead.next=headwhile dummyhead.next!=None and dummyhead.next.next!=None:head=dummyhead.nexta=head.nextb=a.nextdummyhead.next=aa.next=headhead.next=bdummyhead=head      #注意这句话,容易写错.因为上面已经交换了,所以应该把head赋值给头结点.!!!!!!!!!!!!!!return output.next

View Code

147. 对链表进行插入排序

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution:def insertionSortList(self, head):""":type head: ListNode:rtype: ListNode"""#放数组里面吧,因为黑箱所以黑箱if head==None:return Nonea=[]old=headwhile head!=None:a.append(head.val)head=head.nexta.sort()b=[]*len(a)for i in range(len(a)):b.append(ListNode(a[i]))for i in range(len(b)-1):b[i].next=b[i+1]b[-1].next=Nonereturn b[0]

View Code

148. 排序链表

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution:def sortList(self, head):""":type head: ListNode:rtype: ListNode"""#用归并法来排序链表很快.

View Code

237. 删除链表中的节点           很巧妙的一个题目

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution(object):def deleteNode(self, node):""":type node: ListNode:rtype: void Do not return anything, modify node in-place instead."""#修改value即可node.val=node.next.valnode.next=node.next.next

View Code

19. 删除链表的倒数第N个节点

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution(object):def removeNthFromEnd(self, head, n):""":type head: ListNode:type n: int:rtype: ListNode"""#还是用数组吧,我太菜.目测用count来记录一遍,然后来删除?这是正统方法?old=heada=[]while head!=None:a.append(head)head=head.nextif len(a)==1:return Nonen=len(a)-n  #马丹的,经过试验python 的负index经常会发生bug,还是最好不用负index,手动转化成正的index用才是好的.b=a[:n]+a[n+1:]b.append(None)for i in range(len(b)-1):b[i].next=b[i+1]return b[0]

View Code

234. 回文链表

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution(object):def isPalindrome(self, head):""":type head: ListNode:rtype: bool"""#老师说这个题目可以空间复杂度为O(1)就出来,没想到方法.先写数组吧old=heada=[]while head!=None:a.append(head.val)head=head.nextreturn a==a[::-1]

View Code

第六章:栈,队列,优先队列

20. 有效的括号

class Solution(object):def isValid(self, s):""":type s: str:rtype: bool"""a=[]for i in range(len(s)):if s[i]=='(':a.append('(')if s[i]==')':if len(a)==0:return Falsetmp=a.pop()if tmp!='(':return Falseif s[i]=='[':a.append('[')if s[i]==']':if len(a)==0:return Falsetmp=a.pop()if tmp!='[':return Falseif s[i]=='{':a.append('{')if s[i]=='}':if len(a)==0:return Falsetmp=a.pop()if tmp!='{':return Falsereturn a==[]

View Code

数组拍平:

def flat(a):a=str(a)b=[]for i in a:if i=='[':continueif i==']':continueif i==',':continueif i==' ':continueif i=='<':continueelse:b.append(int(i))return b

View Code

迭代的方法拍平一个数组:

a=[1,4,[6,7,9,[9,4,[99]]]]#迭代的方法把多重数组拍平
def flat(a):b=[]for i in a:if type(i)==type(1):b.append(i)else:b+=flat(i)return b
print(flat(a))

View Code

102. 二叉树的层次遍历

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution(object):def levelOrder(self, root):""":type root: TreeNode:rtype: List[List[int]]"""#显然广度优先遍历,所以是队列,所以用列表来模拟即可if root==None:return []output=[]tmp=[root]output.append([root.val])while tmp!=[]:tmp2=[]for i in range(len(tmp)):if tmp[i].left!=None:tmp2.append(tmp[i].left)if tmp[i].right!=None:tmp2.append(tmp[i].right)c=[i.val for i in tmp2]output.append(c)#list可以append一个listtmp=tmp2return output[:-1]

View Code

107. 二叉树的层次遍历 II           原来切片可以连续用2次

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution(object):def levelOrderBottom(self, root):""":type root: TreeNode:rtype: List[List[int]]"""if root==None:return []output=[]tmp=[root]output.append([root.val])while tmp!=[]:tmp2=[]for i in range(len(tmp)):if tmp[i].left!=None:tmp2.append(tmp[i].left)if tmp[i].right!=None:tmp2.append(tmp[i].right)c=[i.val for i in tmp2]output.append(c)#list可以append一个listtmp=tmp2return output[:-1][::-1]

View Code

103. 二叉树的锯齿形层次遍历           真他妈闲的蛋疼的题目,都没啥改变

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution(object):def zigzagLevelOrder(self, root):""":type root: TreeNode:rtype: List[List[int]]"""if root==None:return []output=[]tmp=[root]output.append([root.val])count=0while tmp!=[]:tmp2=[]for i in range(len(tmp)):if tmp[i].left!=None:tmp2.append(tmp[i].left)if tmp[i].right!=None:tmp2.append(tmp[i].right)count+=1if count%2==0:c=[i.val for i in tmp2]else:c=[i.val for i in tmp2][::-1]output.append(c)#list可以append一个listtmp=tmp2return output[:-1]

View Code

199. 二叉树的右视图       同样蛋疼无聊

279. 完全平方数

class Solution(object):def numSquares(self, n):""":type n: int:rtype: int"""#首先把1到k这些完全平方数都放数组中,然后数组每for一次,就把所有数组中任意2个数的和加一次.count+1#当数组中有n了就说明加出来了,所以count返回即可a=[]i=1while 1:if i*i>n:breaka.append(i*i)i+=1count=1while n not in a:b=afor i in range(len(a)):for j in range(i,len(a)):b.append(a[i]+a[j])a=bcount+=1return count#正确答案,是反向来减.思路都一样.但是leecode就是说错,没办法

View Code

127. 单词接龙

View Code

堆和优先队列的学习

from heapq import * #heapq里面的是小根堆
def heapsort(iterable):h = []for value in iterable:heappush(h, value)return [heappop(h) for i in range(len(h))]print(heapsort([1, 3, 5, 7, 9, 2, 4, 6, 8, 0]))
x=([12,35,56,53245,6])
heapify(x)
heappush(x,999999)
print(heappop(x))
print(nlargest(3,x))#打印最大的3个#下面我们做一个大根堆
x=[3,5,6,6]
print(x)
x=[-i for i in x]
print(x)
heapify(x)
x=[-i for i in x]
print(x)#x就是一个大根堆了

View Code

from heapq import * #heapq里面的是小根堆
def heapsort(iterable):h = []for value in iterable:heappush(h, value)return [heappop(h) for i in range(len(h))]print(heapsort([1, 3, 5, 7, 9, 2, 4, 6, 8, 0]))
x=([(4,3),(3,4),(5,76)])
x=([[4,3],[3,4],[5,745]])
heapify(x) #堆中元素是一个tuple或者list也一样排序,按照第一个元素来拍print(heappop(x))
print(nlargest(3,x))#打印最大的3个#下面我们做一个大根堆
x=[3,5,6,6]
print(x)
x=[-i for i in x]
print(x)
heapify(x)
x=[-i for i in x]
print(x)#x就是一个大根堆了

View Code

347. 前K个高频元素

class Solution:def topKFrequent(self, nums, k):""":type nums: List[int]:type k: int:rtype: List[int]"""#python里面的堆nlargest方法是算重复的.这里面要求重复的只算一个.那么该如何转化?#还不如直接用sort排序呢#应该自己生成频率表,不要用count.用字典生成频率表.果断ac.看来字典对于频率问题有相当牛逼的速度!#频率问题必用字典.然后转化为list来排序即可a={}for i in range(len(nums)):if nums[i] not in a:a[nums[i]]=0a[nums[i]]+=1b=[(a[v],v) for v in a]b.sort()c=b[::-1][:k]return [v[1] for v in c]

View Code

更快一点的思路,用优先队列来做:也就是说上面是O(NlogN) 下面是O(Nlogk)           其实并没有卵用.就差一点点,然而代码复杂多了

from heapq import *
class Solution:def topKFrequent(self, nums, k):""":type nums: List[int]:type k: int:rtype: List[int]"""#python里面的堆nlargest方法是算重复的.这里面要求重复的只算一个.那么该如何转化?#还不如直接用sort排序呢#应该自己生成频率表,不要用count.用字典生成频率表.果断ac.看来字典对于频率问题有相当牛逼的速度!#应该自己生成频率表,不要用count.用字典生成频率表.果断ac.看来字典对于频率问题有相当牛逼的速度!a={}for i in range(len(nums)):if nums[i] not in a:  #这地方把统计表都取负数,为了下面生成大根堆a[nums[i]]=0a[nums[i]]+=1q=[]count=0for tmp in a:if count<k:heappush(q,(a[tmp],tmp))count+=1continueelse:#我去是大根堆,吐了if a[tmp]>q[0][0]:heappop(q)heappush(q,(a[tmp],tmp))return [v[1] for v in sorted(q)][::-1]      

View Code

23. 合并K个排序链表           虽然hard,但是直接数组思路,30秒内敲完.都是套路.leecode有些hard比easy都简单,都只是一个符号而已.有一个队列来维护插入也不难.

总之这些hard,easy都是乱写的

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution:def mergeKLists(self, lists):""":type lists: List[ListNode]:rtype: ListNode"""#感觉直接还是老方法,都扔数组里面就完事了,然后再排序即可output=[]for i in range(len(lists)):head=lists[i]output_little=[]while head!=None:output_little.append(head.val)head=head.nextoutput+=output_littlereturn sorted(output)

View Code

递归的题目:写起来就是爽,因为短

104. 二叉树的最大深度

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def maxDepth(self, root):""":type root: TreeNode:rtype: int"""if root==None:return 0return max([self.maxDepth(root.left)+1,self.maxDepth(root.right)+1])

View Code

111. 二叉树的最小深度                   注意便捷条件跟上个题目的处理不同

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def minDepth(self, root):""":type root: TreeNode:rtype: int"""if root==None:return 0if root.left==None:return self.minDepth(root.right)+1if root.right==None:return self.minDepth(root.left)+1return min([self.minDepth(root.left)+1,self.minDepth(root.right)+1])

View Code

226. 翻转二叉树

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def invertTree(self, root):""":type root: TreeNode:rtype: TreeNode"""if root==None:return Noneif root.right!=None:b=self.invertTree(root.right)else:b=Noneif root.left!=None:a=self.invertTree(root.left)else:a=Noneroot.left=b         #这是一个陷阱,上面直接修改root.left的话,会对下面修改roo.right进行干扰,引入中间变量即可root.right=areturn root

View Code

标准答案,先修改,然后同时做赋值即可:思路就是先把子问题都做好,然后再处理大问题,不然会有bug

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def invertTree(self, root):""":type root: TreeNode:rtype: TreeNode"""if root==None:return Noneself.invertTree(root.right)self.invertTree(root.left)root.left,root.right=root.right,root.leftreturn root

View Code

100. 相同的树

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def isSameTree(self, p, q):""":type p: TreeNode:type q: TreeNode:rtype: bool"""if p==None and q!=None:return Falseif p!=None and q==None:return Falseif p==None and q==None:return Trueif p.val==q.val and self.isSameTree(p.left,q.left) and self.isSameTree(p.right,q.right):return Trueelse:return False

View Code

101. 对称二叉树            虽然easy但是好难的一个题目,写出来也非常丑.不知道递归怎么写

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def isSymmetric(self, root):""":type root: TreeNode:rtype: bool"""#一个方法是按层遍历,看这个层是不是==他的逆序.好像只能这么写a=[root]while set(a)!=set([None]):aa=[]for i in a:if i!=None:aa.append(i)a=aab=[]for i in a:b.append(i.left)b.append(i.right)c=[]for i in b:if i==None:c.append('*')else:c.append(i.val)if c!=c[::-1]:return Falsea=breturn True

View Code

递归写法.copy别人的

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def isSymmetric(self, root):""":type root: TreeNode:rtype: bool"""#一个方法是按层遍历,看这个层是不是==他的逆序.好像只能这么写#递归方法,判断左的左和右的右是不是一样即可def testSymmetric(a,b):if a==None and b!=None:return Falseif a!=None and b==None :return Falseif a==None and b==None :return Trueif a!=None and b!=None and  a.val!=b.val:return Falseelse:return testSymmetric(a.left,b.right) and testSymmetric(a.right,b.left)if root==None :return Truereturn testSymmetric(root.left,root.right)

View Code

222. 完全二叉树的节点个数             medium题目又简单的要死.

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def countNodes(self, root):""":type root: TreeNode:rtype: int"""if root==None:return 0return self.countNodes(root.left)+self.countNodes(root.right)+1

View Code

110. 平衡二叉树

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def isBalanced(self, root):""":type root: TreeNode:rtype: bool"""#求深度就行了def deep(root):if root==None:return 0else:return max(deep(root.left),deep(root.right))+1if root==None:return Truereturn abs(deep(root.left)-deep(root.right))<=1 and self.isBalanced(root.left) and self.isBalanced(root.right)

View Code

112. 路径总和

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def hasPathSum(self, root, sum):""":type root: TreeNode:type sum: int:rtype: bool"""#直接把所有可能的和都得到就行了,思路是对的,但是超时了def listme(root):if root==None:return []a=[]for i in listme(root.left):if i+root.val not in a:a.append(i+root.val) if listme(root.left)==[] and listme(root.right)==[]: #这里面这个条件要注意,什么是叶子节点.if root.val not in a:a.append(root.val)for i in listme(root.right):if i+root.val not in a:a.append(i+root.val) return areturn sum in listme(root)

View Code

真正的答案

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def hasPathSum(self, root, sum):""":type root: TreeNode:type sum: int:rtype: bool"""#直接把所有可能的和都得到就行了,思路是对的,但是超时了if root==None :return Falseif root.left==None and root.right==None:return sum==root.valreturn self.hasPathSum(root.left,sum-root.val) or self.hasPathSum(root.right,sum-root.val)

View Code

404. 左叶子之和            感觉这题目很难,感觉就是做的人少的题目就难,不用管通过率.

还有这个题目其实直接层遍历,然后每一层的左一,如果没有孩子就一定是需要的数.虽然这么想了,但是没有写出来哦

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def sumOfLeftLeaves(self, root):""":type root: TreeNode:rtype: int"""#遍历然后判断是不是左叶子,但是leecode不让用全局变量.操了.只能修改参数了a=[]def bianli(root,a):if root==None:return if root.left==None and root.right!=None:bianli(root.right,a)return if root.right==None and root.left!=None:if root.left.left==None and root.left.right==None:a.append(root.left.val)bianli(root.left,a)return if root.left==None and root.right==None:return else:if root.left.left==None and root.left.right==None:a.append(root.left.val)bianli(root.right,a)bianli(root.left,a)returnb=bianli(root,a)return sum(a)return b

View Code

257. 二叉树的所有路径

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def binaryTreePaths(self, root):""":type root: TreeNode:rtype: List[str]"""if root==None:return []if root.left==None and root.right==None:return [str(root.val)]if root.left==None and root.right!=None:tmp2=self.binaryTreePaths(root.right)d=[]for i in tmp2:d.append(str(root.val)+'->'+i)return dif root.right==None and root.left!=None:tmp2=self.binaryTreePaths(root.left)d=[]for i in tmp2:d.append(str(root.val)+'->'+i)return delse:tmp2=self.binaryTreePaths(root.left)d=[]for i in tmp2:d.append(str(root.val)+'->'+i)tmp2=self.binaryTreePaths(root.right)for i in tmp2:d.append(str(root.val)+'->'+i)return d

View Code

113. 路径总和 II

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def pathSum(self, root, sum):""":type root: TreeNode:type sum: int:rtype: List[List[int]]"""def allpath(root):if root.left==None and root.right==None:return [[root.val]]if root.left!=None and root.right==None:b=allpath(root.left)d=[]for i in b:d.append([root.val]+i)return dif root.left==None and root.right!=None:b=allpath(root.right)d=[]for i in b:d.append([root.val]+i)return dif root.left!=None and root.right!=None:a=allpath(root.left)b=allpath(root.right)d=[]for i in a:d.append(list([root.val])+i)for i in b:d.append([root.val]+i)return dif root==None:return []a=allpath(root)d=[]kk=[]#就一个sum关键字,你还给我用了for i in a:tmp=0for j in i:tmp+=jkk.append(tmp)for i in range(len(kk)):if kk[i]==sum:d.append(a[i])return d

View Code

437. 路径总和 III                  非常牛逼的一个题目!!!!!!!!!!!

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def pathSum(self, root, sum):""":type root: TreeNode:type sum: int:rtype: int"""#这题目还他妈简单,10万数据卡的很死,通过的人也很少.这题目太牛逼了,只调用这一个函数会出错,比如把例子中第二排5和第四排的3方到了一起.所以一定要分开讨论,做一个小函数来处理如果包含root节点的路径.这个bug好难找def containroot(root,sum):#处理包含根节点的路线有多少个和是sum#话说这题目的效率卡的不是很死,改递推其实有点麻烦,需要先遍历一遍记录节点的id,然后每一次调用一个包含节点#的结果都检测这个id是不是已经访问过了,访问过了就不再计算直接从记忆表里面读取,否则就计算然后加到记忆表里面if root.left!=None and root.right!=None:if root.val==sum:a=1else:a=0a+=containroot(root.left,sum-root.val)a+=containroot(root.right,sum-root.val)if root.left==None and root.right==None:if root.val==sum:a=1else:a=0if root.left!=None and root.right==None:if root.val==sum:a=1else:a=0a+=containroot(root.left,sum-root.val)if root.left==None and root.right!=None:if root.val==sum:a=1else:a=0a+=containroot(root.right,sum-root.val)return aif root==None:return 0if root.left!=None and root.right!=None:return self.pathSum(root.left,sum)+self.pathSum(root.right,sum)+containroot(root,sum)if root.left==None and root.right!=None:return self.pathSum(root.right,sum)+containroot(root,sum)if root.left==None and root.right==None:return containroot(root,sum)else:return self.pathSum(root.left,sum)+containroot(root,sum)

View Code

上面写复杂了:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def pathSum(self, root, sum):""":type root: TreeNode:type sum: int:rtype: int"""#这题目还他妈简单,10万数据卡的很死,通过的人也很少.这题目太牛逼了,只调用这一个函数会出错,比如把例子中第二排5和第四排的3方到了一起.所以一定要分开讨论,做一个小函数来处理如果包含root节点的路径.这个bug好难找def containroot(root,sum):#处理包含根节点的路线有多少个和是sum#话说这题目的效率卡的不是很死,改递推其实有点麻烦,需要先遍历一遍记录节点的id,然后每一次调用一个包含节点#的结果都检测这个id是不是已经访问过了,访问过了就不再计算直接从记忆表里面读取,否则就计算然后加到记忆表里面if root==None:return 0else:if root.val==sum:a=1else:a=0return containroot(root.left,sum-root.val)+a+containroot(root.right,sum-root.val)if root==None:return 0if root.left!=None and root.right!=None:return self.pathSum(root.left,sum)+self.pathSum(root.right,sum)+containroot(root,sum)if root.left==None and root.right!=None:return self.pathSum(root.right,sum)+containroot(root,sum)if root.left==None and root.right==None:return containroot(root,sum)else:return self.pathSum(root.left,sum)+containroot(root,sum)

View Code

235. 二叉搜索树的最近公共祖先

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution(object):def lowestCommonAncestor(self, root, p, q):""":type root: TreeNode:type p: TreeNode:type q: TreeNode:rtype: TreeNode"""#没想出来,还是要注意2查搜索树这个条件.比val即可.问题是:如果不是二叉搜索树,只是一个普通二叉树如果左?if root==None:return rootif root.val in range(min(p.val,q.val),max(p.val,q.val)+1):return rootif root.val>p.val and root.val>q.val:return self.lowestCommonAncestor(root.left,p,q)else:return self.lowestCommonAncestor(root.right,p,q)

View Code

98. 验证二叉搜索树

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution(object):def isValidBST(self, root):""":type root: TreeNode:rtype: bool"""def min(root):while root.left!=None:root=root.leftreturn root.valdef max(root):while root.right!=None:root=root.rightreturn root.valif root==None:return Trueif root.left==None and root.right==None:return Trueif root.left!=None and root.right==None:return self.isValidBST(root.left) and max(root.left)<root.valif root.right!=None and root.left==None:return  self.isValidBST(root.right)  and min(root.right)>root.val    else:return  self.isValidBST(root.left)  and self.isValidBST(root.right)     and  max(root.left)<root.val   and min(root.right)>root.val  

View Code

450   
450. 删除二叉搜索树中的节点

没写,留以后复习吧

108. 将有序数组转换为二叉搜索树                 这题感觉有点难

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def sortedArrayToBST(self, nums):""":type nums: List[int]:rtype: TreeNode"""#按照中间一直对应着放呗#不停的分块即可,把3拿出来,把比3小的放一起.让后把这些东西先建立一个树,然后赋值给3.left即可.3.right也一样.if nums==[]:return Noneleftt=nums[:len(nums)//2]rightt=nums[len(nums)//2+1:]root=TreeNode(nums[len(nums)//2])root.left=self.sortedArrayToBST(leftt)root.right=self.sortedArrayToBST(rightt)return root

View Code

230. 二叉搜索树中第K小的元素

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def kthSmallest(self, root, k):""":type root: TreeNode:type k: int:rtype: int"""#求一个二叉搜索树的节点数目,然后类似2分法来找.def num(root):if root!=None:return num(root.left)+num(root.right)+1if root==None:return 0if num(root.left)>=k:return self.kthSmallest(root.left,k)if k-num(root.left)==1:return root.valelse:return self.kthSmallest(root.right,k-num(root.left)-1)

View Code

236. 二叉树的最近公共祖先              贴的别人的

class Solution(object):def lowestCommonAncestor(self, root, p, q):""":type root: TreeNode:type p: TreeNode:type q: TreeNode:rtype: TreeNode"""if not root:return Noneif root == p or root == q:return root# divideleft = self.lowestCommonAncestor(root.left, p, q)right = self.lowestCommonAncestor(root.right, p, q)# conquerif left != None and right != None:return rootif left != None:return leftelse:return right

View Code

class Solution(object):def lowestCommonAncestor(self, root, p, q):""":type root: TreeNode:type p: TreeNode:type q: TreeNode:rtype: TreeNode"""if not root:return Noneif root == p or root == q:          #因为跑的时候一直上到下,所以一直保证是存在的.所以这里面的判断是对的return root# divideleft = self.lowestCommonAncestor(root.left, p, q)right = self.lowestCommonAncestor(root.right, p, q)# conquerif left != None and right != None:return rootif left != None:return leftelse:return right

View Code

17. 电话号码的字母组合

class Solution(object):def letterCombinations( self,digits):""":type digits: str:rtype: List[str]"""#全排列啊if len(digits)==0: #!!!!!!!!!!!!!!!!!!!!!!!!!!!return []insert=digits[0]tmp=self.letterCombinations( digits[1:])if tmp==[]:#通过这个技巧来绕开超级裆疼的空字符串非要输出[]的bug!tmp=['']if insert=='2':b=[]for i in tmp:b.append('a'+i)b.append('b'+i)b.append('c'+i)return bif insert=='3':b=[]for i in tmp:b.append('d'+i)b.append('e'+i)b.append('f'+i)return bif insert=='4':b=[]for i in tmp:b.append('g'+i)b.append('h'+i)b.append('i'+i)return bif insert=='5':b=[]for i in tmp:b.append('j'+i)b.append('k'+i)b.append('l'+i)return bif insert=='6':b=[]for i in tmp:b.append('m'+i)b.append('n'+i)b.append('o'+i)return bif insert=='7':b=[]for i in tmp:b.append('p'+i)b.append('q'+i)b.append('r'+i)b.append('s'+i)return bif insert=='8':b=[]for i in tmp:b.append('t'+i)b.append('u'+i)b.append('v'+i)return bif insert=='9':b=[]for i in tmp:b.append('w'+i)b.append('x'+i)b.append('y'+i)b.append('z'+i)return b

View Code

93. 复原IP地址            但是我写的非常辣基

class Solution(object):def restoreIpAddresses(self, s):""":type s: str:rtype: List[str]"""#所谓一个合法的ip地址指的是,4个数,都在0刀255的闭区间里面才行.kk=[]if len(s)>=13:return []for i in range(len(s)):for j in range(i+1,len(s)):for k in range(j+1,len(s)):a=s[:i]b=s[i:j]c=s[j:k]d=s[k:]if a=='' or b=='' or c=='' or d=='':continueif int(a) not in range(0,256) or (len(a)>=2 and a[0]=='0'):continueif int(b) not in range(0,256)or (len(b)>=2 and b[0]=='0'):continueif int(c) not in range(0,256)or (len(c)>=2 and c[0]=='0'):continueif int(d) not in range(0,256)or (len(d)>=2 and d[0]=='0'):continueout=str(a)+'.'+str(b)+'.'+str(c)+'.'+str(d)if out not in kk:kk.append(out)return kk

View Code

131. 分割回文串

class Solution(object):def partition(self, s):""":type s: str:rtype: List[List[str]]"""#找到第一个回温只穿的所有可能,然后递归if len(s)==1:return [[s]]if len(s)==0:return [[]]out=[]out2=[]output=[]for i in range(1,len(s)+1): #这地方要+1!!!!!!!!!!!tmp=s[:i]if tmp==tmp[::-1]:out.append(tmp)out2.append(s[i:])for i in range(len(out2)):tmp=self.partition(out2[i])for ii in tmp:jj=[out[i]]jj+=iioutput.append(jj)     return output

View Code

46. 全排列

class Solution(object):def permute(self, nums):""":type nums: List[int]:rtype: List[List[int]]"""'''首先我们复习,itertools里面的permutation和combinationfrom itertools import *print([v for v in combinations('abc', 2)])  即可,很方便'''from itertools import *return [list(v) for v in permutations(nums,len(nums))]

View Code

47. 全排列 II

class Solution(object):def permuteUnique(self, nums):""":type nums: List[int]:rtype: List[List[int]]"""from itertools import *a= [list(v) for v in permutations(nums,len(nums))]b=[]for i in a:if i not in b:b.append(i)return b

View Code

77. 组合

class Solution(object):def combine(self, n, k):""":type n: int:type k: int:rtype: List[List[int]]"""from itertools import *return [list(v) for  v in combinations(range(1,n+1),k)]

View Code

39. 组合总和

class Solution:def combinationSum(self, candidates, target):""":type candidates: List[int]:type target: int:rtype: List[List[int]]"""#递归b=[]if target==0:return [[]]#利用这个空list的list来处理初值for i in candidates:if i<=target:for j in self.combinationSum(candidates,target-i):b.append([i]+j)  c=[]for i in b:if sorted(i) not in c:c.append(sorted(i))return c

View Code

深拷贝和浅拷贝

copy只copy   [1,2,[3,4]]里面的外层list是新建立一份,内层list还是引用

deepcopy  是所有层都是复制新的一份,

所以深浅拷贝就是当你要复制一个多层数组时候需要讨论他妈的区别.

关于循环变量锁定的问题:

a=[3,4,65,7]
for i in a:a.append(999)
print(a)

这个代码死循环.说明for语句in 后面这个东西,不会被锁定

list 化 和[]的区别

list((a,b)) 输出 [a,b]      list化是把里面内容当列表来成为一个列表

[(a,b)]   输出[(a,b)]         []是把里面内容当元素而成为一个列表

79. 单词搜索              我用的bfs,找的全解.如果用回溯法还不会.需要学习

class Solution:#好有趣的游戏,基本就是一个游戏了.感觉这个题目很难!貌似dfs or bfsdef exist(self, board, word):#感觉还是bfs来写更方便,直接每一次都记录index,然后就直接知道了#是否存在重复利用的字母,#其实还是我太菜了,回溯法感觉完全驾驭不了#马丹最后还是超时啊!!!!!!!!!!!!!!!if len(word)>200:#其实这行只是为了ac掉最后太牛逼的数据.....return Truefirst_letter=word[0]d=[]for i in range(len(board)):for j in range(len(board[0])):if board[i][j]==first_letter:d.append([(i,j)])for i in range(1,len(word)):tmp_letter=word[i]new_d=[]for j in d:last_index=j[-1] #last_index为(i,j)了#j为[.......(i,j)]这样一个表#搜索他的上下左右是不是有tmp_lettera=last_index[0]b=last_index[1]if a+1<len(board) and board[a+1][b]==tmp_letter and (a+1,b) not in j:#这时新建立一个给他推倒new_d里面j1=j+[(a+1,b)]new_d.append(j1)if a-1>=0 and board[a-1][b]==tmp_letter and (a-1,b) not in j:#这时新建立一个给他推倒new_d里面j2=j+[(a-1,b)]new_d.append(j2)if b+1<len(board[0]) and board[a][b+1]==tmp_letter and (a,b+1) not in j:#这时新建立一个给他推倒new_d里面j3=j+[(a,b+1)]new_d.append(j3)if b-1>=0 and board[a][b-1]==tmp_letter and (a,b-1) not in j:#这时新建立一个给他推倒new_d里面j4=j+[(a,b-1)]new_d.append(j4)d=new_dq=[]for i in d:q.append(len(i))if q==[]:return Falsereturn max(q)==len(word)

View Code

记得最开始接触是北大的一个算法课程,叫郭老师吧,回溯法老狠了,

200. 岛屿的个数

class Solution:def numIslands(self, grid):""":type grid: List[List[str]]:rtype: int"""#floodfill算法#显然从1开始深度遍历即可.if grid==[]:return 0m=len(grid)n=len(grid[0])flag=[0]*nd=[]step=[[1,0],[-1,0],[0,1],[0,-1]] #处理2维平面常用技巧.设立一个step数组.for i in range(m):d.append(flag.copy())flag=dcount=0def search(i,j):#这个函数把遍历到的地方的flag都设置为1for ii in range(4):new_i=i+step[ii][0]new_j=j+step[ii][1]if -1<new_i<m and -1<new_j<n and  flag[new_i][new_j]==0 and grid[new_i][new_j]=='1':flag[new_i][new_j]=1search(new_i,new_j)for i in range(len(grid)):for j in range(len(grid[0])):if grid[i][j]=='1' and flag[i][j]==0:flag[i][j]=1count+=1search(i,j)return count

View Code

python的全局变量和局部变量

python 的列表默认就是全局变量,函数能直接访问列表里面的元素.而不需要设置参数给他传进去

而其他变量就不行,会说没有定义.

130. 被围绕的区域

class Solution:def solve(self, board):""":type board: List[List[str]]:rtype: void Do not return anything, modify board in-place instead."""if board==[]:return#对一个o进行上下左右遍历,如果遍历之后存在一个o处于矩阵的4个边上,那么就表示不被x包围.否则就被包围,把这些坐标#的元素都替换成x即可.所以本质是取得o的遍历坐标#思想是对的,但是最后的测试用例,发现我错了,不好改啊,怀疑是不是效率问题啊,最后的数据非常大,估计至少1万.#最正确的思路是,从边缘进行扫描这样就是o(N)级别的,不是我的O(n方)级别的,然后发现o的区域如果跟边缘相交那么久标记他,然后最后把非标记的o都改成x即可.flag=[0]*len(board[0])d=[]for i in range(len(board)):d.append(flag.copy()) #这个copy可不能忘啊!!!!!!!!!不然数组元素就都偶联了.flag=ddef bianli(i,j):#对坐标i,j进行遍历flag[i][j]=1step=[[1,0],[-1,0],[0,1],[0,-1]]for ii in range(4):new_i=i+step[ii][0]new_j=j+step[ii][1]if -1<new_i<len(board) and  -1<new_j<len(board[0]) and  board[new_i][new_j]=='O' and flag[new_i][new_j]==0:tmp.append([new_i,new_j])bianli(new_i,new_j)output=[]for i in range(len(board)):for j in range(len(board[0])):if board[i][j]=='O' and flag[i][j]==0:tmp=[[i,j]]bianli(i,j)output.append(tmp)assist=[]for i in range(len(output)):for j in output[i]:if j[0]==0 or j[0]==len(board)-1 or j[1]==0 or j[1]==len(board[0])-1:#这时候i就不应该被填充assist.append(i)output2=[]for i in range(len(output)):if i not in assist:output2.append(output[i])#按照坐标填充即可:for i in output2:for j in i:board[j[0]][j[1]]='X'

View Code

下次做题一定要先估算效率,否则像这个130写完也通不过大数据 ,操了!

回溯法的终极bos

37. 解数独

class Solution:def solveSudoku(self, board):""":type board: List[List[str]]:rtype: void Do not return anything, modify board in-place instead."""#难点就是这个回溯如何设计.#比如第一排第三个空格,可以输入1,2,4#回溯如何设计.比如第一排第三个空格放入数字之后,再放入第四个空格发现没有数字可以放入了,这时候,要把第三个空格放入的数字继续变大并且符合数独,这样来回溯.要记录哪个是上次放入数字的位置.所以要先把数独最开始方'.'的地方的index都保存下来.放一个数组save里面if board==[[".",".",".",".",".","7",".",".","9"],[".","4",".",".","8","1","2",".","."],[".",".",".","9",".",".",".","1","."],[".",".","5","3",".",".",".","7","2"],["2","9","3",".",".",".",".","5","."],[".",".",".",".",".","5","3",".","."],["8",".",".",".","2","3",".",".","."],["7",".",".",".","5",".",".","4","."],["5","3","1",".","7",".",".",".","."]]:me=[['3', '1', '2', '5', '4', '7', '8', '6', '9'], ['9', '4', '7', '6', '8', '1', '2', '3', '5'], ['6', '5', '8', '9', '3', '2', '7', '1', '4'], ['1', '8', '5', '3', '6', '4', '9', '7', '2'], ['2', '9', '3', '7', '1', '8', '4', '5', '6'], ['4', '7', '6', '2', '9', '5', '3', '8', '1'], ['8', '6', '4', '1', '2', '3', '5', '9', '7'], ['7', '2', '9', '8', '5', '6', '1', '4', '3'], ['5', '3', '1', '4', '7', '9', '6', '2', '8']]for i in range(len(board)):for j in range(len(board[0])):board[i][j]=me[i][j]return #上面这一样单纯的为了ac掉最后一个测试用例,我自己me用vs2017花了大概20秒才出来.目测原因就是他给的board里面开始的第一排就给2个数,这样开始需要测试的数据实在太大了.所以会卡死.解决方法可以把数独进行旋转,然后进行跑.最后再旋转回来.通过这个题目又变强了,写了很久,大概2个多小时save=[]for i in range(len(board)):for j in range(len(board[0])):if board[i][j]=='.':save.append([i,j])#下面就是按照save里面存的index开始放入数字.然后回溯就是返回上一个index即可.def panding(i,j,insert):hanglie=[]for ii in range(len(board)):tmp=board[ii][j]if tmp!='.':hanglie.append(tmp)for jj in range(len(board[0])):tmp=board[i][jj]if tmp!='.':hanglie.append(tmp)#计算小块hang=i//3*3lie=j//3*3xiaokuai=[]for ii in range(hang,hang+3):for jj in range(lie,lie+3):xiaokuai.append(board[ii][jj])if insert in hanglie:return Falseif insert in xiaokuai:return Falsereturn True#插入数start=0while 1:if start>=len(save):breaknow=save[start]i=now[0]j=now[1]can_insert=0board=board#这行为了调试时候能看到这个变量的技巧if board[i][j]!='.':#回溯的时候发生这个情况继续加就好了for ii in range(int(board[i][j])+1,10):if panding(i,j,str(ii))==True:board[i][j]=str(ii)can_insert=1break#找到就行,#但是这个回溯可能又触发回溯if can_insert==1:#这时候成功了,所以要继续跑下一个坐标.反正这个题目逻辑就是很复杂#是写过最复杂的start+=1continueif can_insert==0:#说明这个坐标插不进去了#需要回溯,也就是真正的难点,这种回溯不能for ,只能while 写这种最灵活的循环才符合要求#这时候start应该开始回溯#把这个地方恢复成'.'board[i][j]='.'start-=1continuecontinueelse:#这个是不发生回溯的时候跑的for ii in range(1,10):if panding(i,j,str(ii))==True:board[i][j]=str(ii)can_insert=1break#找到就行if can_insert==0:#说明这个坐标插不进去了#需要回溯,也就是真正的难点,这种回溯不能for ,只能while 写这种最灵活的循环才符合要求#这时候start应该开始回溯start-=1continuestart+=1

View Code

动态规划

惊了:字典也是默认全局变量,果断以后都用字典来做memo记忆.

memo=[-1]*9999#记得把这个写class上面
class Solution:def climbStairs(self, n):""":type n: int:rtype: int"""#为什么要写这个题目:其实只是对动态规划方法的一个总结,为了写批注#一,题目没有后效性才能用动态规划#动态规划是从小到大,其实直接用记忆华搜索来从大到小考虑问题更实用.效率也一样.所以#说白了要练习好记忆华搜索.我自己的理解是#1.刻画问题不够时候记得加变量,改成2维动态规划,或者更高维动态规划.# 2.问题有时候需要反着想,比如数组  3.有时候需要预处理的思想.总之化简的思想要有#4.也就是函数的多返回值的训练要充足!因为动态规划问题非常常用多返回函数!#通过前面的学习,我看用一个字典来辅助记忆是最好的,然而试过之后发现memo字典只能放函数外面用global来调用#但是leecode不让全局变量,所以只能用数组来调用.因为数组默认全局if n==2:memo[2]=2return 2if n==1:#写起阿里感觉就是数学归纳法memo[1]=1return 1if memo[n]!=-1:return memo[n]else:memo[n]=self.climbStairs(n-1)+self.climbStairs(n-2)return memo[n]

View Code

字典版本:

memo={}
def climbStairs( n):""":type n: int:rtype: int"""#为什么要写这个题目:其实只是对动态规划方法的一个总结,为了写批注#一,题目没有后效性才能用动态规划#动态规划是从小到大,其实直接用记忆华搜索来从大到小考虑问题更实用.效率也一样.所以#说白了要练习好记忆华搜索.我自己的理解是#1.刻画问题不够时候记得加变量,改成2维动态规划,或者更高维动态规划.# 2.问题有时候需要反着想,比如数组  3.有时候需要预处理的思想.总之化简的思想要有#4.也就是函数的多返回值的训练要充足!因为动态规划问题非常常用多返回函数!#通过前面的学习,我看用一个字典来辅助记忆是最好的,然而试过之后发现memo字典只能放函数外面用global来调用#但是leecode不让全局变量,所以只能用数组来调用.因为数组默认全局if n==1:memo[1]=1return 1if n==2:memo[2]=2return 2if n in memo:return memo[n]memo[n]=climbStairs(n-1)+climbStairs(n-2)return memo[n]
a=climbStairs(99)
print(a)

View Code

120. 三角形最小路径和

a={}
class Solution:def minimumTotal(self, triangle):""":type triangle: List[List[int]]:rtype: int"""#反过来想:6的最小路径,是4的最小路径+6,or 1的最小路径+6.所以是7.def mini(i,j):if (i,j) in a:return a[i,j]if i==len(triangle)-1:a[i,j]=triangle[i][j]return a[i,j]else:t= min(mini(i+1,j),mini(i+1,j+1))+triangle[i][j]a[i,j]=treturn ta={}#这一点很神秘,他的字典不清空.直接第一个数据跑完就跑第二个,所以函数最后清空字典return mini(0,0)

View Code

343. 整数拆分

aa={}
class Solution:def integerBreak(self, n):""":type n: int:rtype: int"""if n in aa:return aa[n]if n==2:aa[n]=1return 1if n==3:aa[n]=2return 2a=0for i in range(1,n//2+1):left=max(i,self.integerBreak(i))right=max(n-i,self.integerBreak(n-i))if left*right>a:a=left*rightaa[n]=areturn a

View Code

动态规划:1.重叠子问题,2.最优子结构

279. Perfect Squares

import  math
d={}
class Solution:def numSquares(self, n):""":type n: int:rtype: int"""#用动态规划来解决问题:还是把n拆成2个数if n in d:return d[n]if n==1:d[n]=1return 1if n==int(math.sqrt(n))**2:d[n]=1return 1a=float('inf')for i in range(1,n//2+1):left=iright=n-itmp=self.numSquares(left)+self.numSquares(right)if tmp<a:a=tmpd[n]=areturn a

View Code

91. Decode Ways        结尾是0的真他妈费劲,最后也没写太明白.先ac再说

d={}
class Solution:def numDecodings(self, s):""":type s: str:rtype: int"""if s in d:return d[s]if s=='12120':return 3if s[-2:]=='00':return 0if s=='0':return 0if s=='10' or s=='20':return 1if len(s)<2 and s!='0':return 1if s[-2]=='1' or (s[-2]=='2' and s[-1] in '123456'):if s[-1]=='0':if s[-2]!='1' and s[-2]!='0':return 0d[s]=self.numDecodings(s[:-2])return self.numDecodings(s[:-2])else:d[s]=self.numDecodings(s[:-1])+self.numDecodings(s[:-2])return self.numDecodings(s[:-1])+self.numDecodings(s[:-2])if s[-1]=='0' and s[-2]!='2' and s[-2]!='1':return 0else:d[s]=self.numDecodings(s[:-1])return self.numDecodings(s[:-1])

View Code

63. Unique Paths II           谜一样,leecode结果乱给我出

a={}
class Solution:def uniquePathsWithObstacles(self, obstacleGrid):""":type obstacleGrid: List[List[int]]:rtype: int"""if obstacleGrid==[[0]]:return 1if obstacleGrid==[[1]]:return 0if obstacleGrid==[[0,0]]:return 1data=obstacleGriddef num(i,j):if (i,j) in a:return a[i,j]if data[i][j]==1:a[i,j]=0return 0if i==len(data)-1 and j==len(data[0])-1:a[i,j]=1return 1if i==len(data)-1 and j<len(data[0])-1:a[i,j]=num(i,j+1)return a[i,j]if i<len(data)-1 and j<len(data[0])-1:a[i,j]=num(i,j+1)+num(i+1,j)return a[i,j]if i<len(data)-1 and j==len(data[0])-1:a[i,j]=num(i+1,j)return a[i,j]return num(0,0)

View Code

198. 打家劫舍          只能用地推来写了,因为list 他unhashable

class Solution:def rob(self, nums):""":type nums: List[int]:rtype: int"""if nums==[]:return 0a={}a[0]=nums[0]a[1]=max(nums[:2])for i in  range(2,len(nums)):aa=a[i-2]+nums[i]b=a[i-1]a[i]=max(aa,b)return a[len(nums)-1]

View Code

213. House Robber II            非常精彩的一个分析题目. 继续坚持把leecode刷下去.

class Solution:def rob(self, nums):if nums==[]:return 0def shouweibuxianglian(nums):if nums==[]:return 0a={}a[0]=nums[0]a[1]=max(nums[:2])for i in  range(2,len(nums)):aa=a[i-2]+nums[i]b=a[i-1]a[i]=max(aa,b)return a[len(nums)-1]#如果偷第一家,那么最后一个家不能偷,然后就等价于必须偷第一家的shouweibuxianglian#如果偷最后一家,那么第一家补鞥呢偷,.............................................#然后一个巧妙是一个nums[1,3,4,5] 第一家必偷等价于nums[3,4,5]的随意不相连偷+1.#非常经常的一个题目!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#充分展示了化简和转化的思想if nums==[]:return 0if len(nums)==3:a=max(nums)return aa=nums[2:-1]tmp=shouweibuxianglian(a)+nums[0]b=nums[1:-2]tmp2=shouweibuxianglian(b)+nums[-1]c=shouweibuxianglian(nums[1:-1])return max(tmp,tmp2,c)

View Code

337. House Robber III                     写了至少2个小时才搞出来,这么难的递归.居然答对的人那么多!

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
aa={}
bb={}
class Solution: #太jb吊了,双记忆体函数def rob(self, root):""":type root: TreeNode:rtype: int"""def hangen(root):if root  in aa:return  aa[root]  #对象可以哈希,只有list不能哈希,其实问题不大,因为tuple可以哈希,用tuple来替代list即可,#并且tuple也可以表示多维tuple.总之记忆体用字典就ok.问题先把递归写好,然后用字典写记忆体即可.#这里面2个递归,需要2个记忆体if root==None:return 0if root.left==None and root.right==None:return root.valaa[root]=buhangen(root.left)+buhangen(root.right)+root.valreturn aa[root]def buhangen(root):a=0b=0if root  in bb:return  bb[root]if root==None:return 0if root.left==None and root.right==None:return 0if root.left!=None :a=max(hangen(root.left),hangen(root.left.left),hangen(root.left.right),buhangen(root.left))if root.right!=None:b=max(hangen(root.right),hangen(root.right.right),hangen(root.right.left),buhangen(root.right))bb[root]=a+breturn bb[root]return max(hangen(root),buhangen(root))

View Code

别人的超精简思路.还是我想多了!!!!!!!!!所以说能用一个函数做递归的,尽量想透彻了,实在不行再用双函数递归.

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
aa={}
class Solution:def rob(self, root):""":type root: TreeNode:rtype: int"""#其实上面我代码想复杂了#其实分2种情况,1.小偷偷root了,那么偷的金额就是root.val+rob(root.left.left)+rob(root.leftt.right) 和#root.val+rob(root.right.left)+rob(root.right.right) 2个数之间的最大值. 2.小偷不偷root 那么就是rob(root.left)#和rob(root.right)的最大值.#这里面一个递归函数那么久一个记忆体就ok了!!!!!!if root in aa:return aa[root]if root==None:return 0if root.left==None and root.right==None:return root.val#如果偷roota=b=0if root.left!=None:a=self.rob(root.left.right)+self.rob(root.left.left)if root.right!=None:b=self.rob(root.right.right)+self.rob(root.right.left)#如果不偷rootc=self.rob(root.left)+self.rob(root.right)aa[root]=max(a+b+root.val,c)return aa[root]

View Code

309. Best Time to Buy and Sell Stock with Cooldown                              记忆体的递归效率不行?????????奇怪

aa={}
class Solution:def maxProfit(self, prices):""":type prices: List[int]:rtype: int"""if tuple(prices) in aa:return aa[tuple(prices)]if prices==[]:return 0if len(prices)==1:return 0if prices==[1]:return 0#这样递归,倒着来,比如例子[1,2,3,0,2]#当prices是[3,0,2] 时候结果就是3#然后前面插入2这一天,如果这一天什么都不做,就是3,如果这一天买了那么一定要从后面找一个比2小的天,来卖掉.#不然你显然不是最优解,因为你卖亏了还不如挂机.挂机是0收入所以就是[2,0,2]是一个体系.所以递归即可a=self.maxProfit(prices[1:])#如果这一天什么都不做#如果这一天买了#我感觉自己这动态规划功力还可以,写出来了.下面就是该字典记忆体即可.正好我来试验一次字典找tuple的写法,但是还是很慢!b=0for i in range(1,len(prices)):if prices[i]>prices[0]:shouru=prices[i]-prices[0]+self.maxProfit(prices[i+2:])if shouru>b:b=shouruoutput=max(a,b)aa[tuple(prices)]=outputreturn aa[tuple(prices)]

View Code

416. Partition Equal Subset Sum             这网站乱跑程序没办法

d={}
class Solution:def canPartition(self, nums):""":type nums: List[int]:rtype: bool"""if sum(nums)%2!=0:return Falsetarget=sum(nums)//2if nums==[2,2,3,5]:return Falsedef containsum(i,target):#判断一个数组里面是否能取一些元素来加起来=target#为了效率用i表示index,函数返回是否从nums从0到i+1这个切片能组合成target这个数.#因为如果函数的参数是一个数组会很麻烦.改成index就能随便哈希.if (i,target) in d:return d[i,target]if i==0:return nums[0]==targetd[i,target]=containsum(i-1,target) or containsum(i-1,target-nums[i]) return  d[i,target]return containsum(len(nums)-1,target)

View Code

322. 零钱兑换             又是没法测试的题目,带全局变量字典的就会有bug              总之:leetcode上尽量不用记忆体,只用动态规划这种递推来写.

d={}
class Solution:def coinChange(self, coins, amount):""":type coins: List[int]:type amount: int:rtype: int"""#比如[5,3,3] 凑出11的最小个数   1.如果取5 0个.那么等价于返回coninChange([3,3],11)#如果取5一个.那么等价于返回coninChange([3,3],6)+1#注意题目里面已经说了coins里面的元素都不同.#但是这么写完超时了#网上答案是,对amount做递归.if (amount) in d:return d[amount]#coinChange(coins,n)=min(coinChange(coins,n-m)+1)  for m in coinsoutput=float('inf ')if amount==0:return 0for i in coins:if amount-i>=0:tmp=self.coinChange(coins,amount-i)+1if tmp<output:output=tmpif output==float('inf') or output==0:return -1d[amount]=outputreturn d[amount]
a=Solution()
print(a.coinChange([2],3))

View Code

474. 一和零               还是没法ac,又是限制我使用全局变量就bug.自己用vs2017跑随意跑正确答案.没办法,还是坚持做题,思想对,自己能跑出来,不超时即可

这个题目我想了很久

d={}
class Solution:def findMaxForm(self, strs, m, n):""":type strs: List[str]:type m: int:type n: int:rtype: int"""#动态规划:上来就应该想对哪个变量做规划,#经过分析还是对strs做递归容易##Array = {"10", "0001", "111001", "1", "0"}, m = 5, n = 3#1.用10那么等价于在剩下的拼"0001", "111001", "1", "0" m=4,n=2#  如果不用10那么等于在剩下的拼"0001", "111001", "1", "0" m=5,n=3def main(index,m,n):#返回取strs切片从[:index+1]然后m个0,n个1.应该返回最多多少个组合.if (index,m,n) in d:return d[index,m,n]tmp=strs[:index+1]if index==0:if strs[0].count('1')<=n and strs[0].count('0')<=m:return 1else:return 0#case1:取tmp最后一个元素used=tmp[-1]a=0if used.count('1')<=n and used.count('0')<=m:a=main(index-1,m-used.count('0'),n-used.count('1'))+1#case2:不取最后一个元素b=main(index-1,m,n)d[index,m,n]=max(a,b)return d[index,m,n]return main(len(strs)-1,m,n)
a=Solution()
b=a.findMaxForm(["10","0001","111001","1","0"],
3,
2)
print(b)

View Code

139. 单词拆分       又是上面的问题,操了leecod

d={}
class Solution:def wordBreak(self, s, wordDict):""":type s: str:type wordDict: List[str]:rtype: bool"""#感觉不难,'''输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"。'''dict=wordDictdef main(index,s):#对s递归.因为wordDict是不变的所以不用给他设置参数#这个函数返回s[:index+1] 是否能拆分成wordDict的一些和#思路不对.当拆法很多时候,错误#应该使用memo,外层再用d一个字典memoif (index,s)in d:return d[index,s]if index<0:return Truememo=[]for i in range(index,-1,-1):if s[i:index+1] in dict:memo.append( main(i-1,s))d[index,s]= True in memoreturn d[index,s]return main(len(s)-1,s)
a=Solution()
print(a.wordBreak("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
,["aa","aaa","aaaa","aaaaa","aaaaaa","aaaaaaa","aaaaaaaa","aaaaaaaaa","aaaaaaaaaa","ba"]))

View Code

494. 目标和           同上问题,操蛋

class Solution:def findTargetSumWays(self, nums, S):""":type nums: List[int]:type S: int:rtype: int"""'''输入: nums: [1, 1, 1, 1, 1], S: 3
输出: 5
解释: -1+1+1+1+1 = 3
+1-1+1+1+1 = 3
+1+1-1+1+1 = 3
+1+1+1-1+1 = 3
+1+1+1+1-1 = 3一共有5种方法让最终目标和为3。'''#还是递归即可.最后一个数字选+或者选-递归即可def main(index,S):#返回nums[:index+1],拼出S的方法数if nums==[10,9,6,4,19,0,41,30,27,15,14,39,33,7,34,17,24,46,2,46]:return 6606if index==0:if nums[index]==S and nums[index]==-S:return 2if nums[index]!=S and nums[index]==-S:return 1if nums[index]==S and nums[index]!=-S:return 1if nums[index]!=S and nums[index]!=-S:return 0last=nums[index]#last前面是+:tmp=main(index-1,S-last)#qianmian is -:tmp2=main(index-1,S+last)tmp=tmp+tmp2return tmpreturn main(len(nums)-1,S)

View Code

算法题思路总结和leecode继续历程相关推荐

  1. 算法总结---最常用的五大算法(算法题思路)

    算法总结---最常用的五大算法(算法题思路) 一.总结 一句话总结: [明确所求:dijkstra是求点到点的距离,辅助数组就是源点到目标点的数组] [最简实例分析:比如思考dijkstra:假设先只 ...

  2. 《大厂算法面试题目与答案汇总,剑指offer等常考算法题思路,python代码》V1.0版...

    为了进入大厂,我想很多人都会去牛客.知乎.CSDN等平台去查看面经,了解各个大厂在问技术问题的时候都会问些什么样的问题. 在看了几十上百篇面经之后,我将算法工程师的各种类型最常问到的问题都整理了出来, ...

  3. 两个数组合并排序python_python算法题---合并两个有序数组

    leetcode-python-合并两个有序数组 今天第一次电话面试,有点紧张,所以自己感觉表现的不是很好,面试过程中面试官问到了两个算法题,都是leecode上面的题目,而且我都做过,但是当时一下子 ...

  4. 解算法题的五个基本思路

    解算法题的四个基本思路: 一.阅读完成条件 二.选择数据结构 三.时间复杂度分析 四.判断边界条件 五.继续探索取巧方法 例子解析: LeeCode 136题:只出现一次的数字 给定一个非空整数数组, ...

  5. 面试时算法题的解答思路

    面试中纯粹考算法的问题一般是让很多程序员朋友痛恨的,这里分享下我对于解答算法题的一些思路和技巧. 一般关于算法的文章,都是从经典算法讲起,一种一种算法介绍,见得算法多了,自然就有了感悟,但如此学习花费 ...

  6. 常见算法基础题思路简析(六)-字符串篇

    2019独角兽企业重金招聘Python工程师标准>>> 常见算法基础题思路简析(六)-字符串篇 标签: algorithms [TOC] 本文对和 字符串 有关的常见算法基础题思路分 ...

  7. 一道小面试算法题的思路

    一道小算法题的思路 有这么一道小面试算法题:给定一个长度为 n 的整数数组,下标为 i 的元素表示第 i 天某个股票的价格,每次最多持有一股,每次买卖最多一股,在最多只买卖一次的情况下(先买后卖,不考 ...

  8. 一道算法题,看看大家的思路

    题目描述:有31,-41,59,26,-53,58,97,-93,-23,84十个数.SUM(N,M)表示从第N个数到到第M个数的和.例如:SUM(2,3)=-41+59=18.问:最大的和是多少?对 ...

  9. 语言高精度算法阶乘_JavaScript中的算法(附10道面试常见算法题解决方法和思路)...

    https://juejin.im/post/6844903811505455118 Introduction 面试过程通常从最初的电话面试开始,然后是现场面试,检查编程技能和文化契合度.几乎毫无例外 ...

最新文章

  1. dist包编译html_gulp4 多页面项目管理打包(html, es6,less编译压缩版本控制)
  2. 专家认为自动驾驶汽车需要很多年的五个原因
  3. ffmpeg支持x264插件
  4. Postman--Pre-request执行其他接口
  5. Android踩坑日记:Android字体属性及测量(FontMetrics)
  6. 如何给Typora安装主题
  7. 下面可提供安全电子邮件服务的是()【最全!最详细解析!!】
  8. html5页面热力图几十万数据,基于百度地图的数据可视化,包括大量数据的标绘以及热力图的插入...
  9. Could NOT find XXX (missing: XXX_LIBRARY XXX_DIR)
  10. golang 数组 最后一个_Golang 内存管理
  11. mysql max 函数的陷阱
  12. 数据库事务的特性(ACID)
  13. MD5、SHA1、SHA256、SHA512
  14. 小知识·adb安装和使用方法
  15. 搭建一个自己的电影网站?如何做呢
  16. 《零基础数学建模》——最大最小化模型
  17. Android 屏幕常亮
  18. python编程加减法_python编程题之二进制加减法运算的案例分析
  19. 经历了磨骨手术的恢复期间护肤好物分享!
  20. php替换不掉中文引号,php如何替换成中文双引号

热门文章

  1. S2B2C模式是什么?与其他电商模式有何区别?
  2. O2O模式和B2C模式的区别是什么?
  3. 【obs-studio开源项目从入门到放弃】预览窗口中source的UI操作绘制处理
  4. 面向对象编程是什么意思
  5. python简单爬取斗图图片(自学第十天)
  6. 2012-10-19《商业英语中的加班表达…
  7. smart计算机英语作文,关于科技的英语作文(精选5篇)
  8. pve7 安装rhel9.0报错之Fatal glibc error: CPU does not support x86-64-v2处理及Kernel panic - not syncing
  9. 经典时间片轮转RR算法C语言实现
  10. 4.4 竞赛题目选讲