Algorithm
Level1 --Binary search
704. Binary Search
用二分法模版
注意两种版本的区别,否则报错
first = 0
end = len(nums)#end不会成为索引溢出
while first < end:#不能重合
mid = (first +end)//2
if nums[mid] == target:
return mid
elif nums[mid]> target:
end = mid
else:
first = mid+1
return -1
first = 0
end = len(nums) - 1
while(first <= end):#能重合
mid = int((first + end)//2)
if nums[mid] == target:
return mid
elif nums[mid] < target:
first = mid + 1
else:
end = mid - 1
return -1
278. First Bad Version
注意用start + (end-start)/2避免溢出
def firstBadVersion(self, n: int) -> int:
first = 1
end = n
while first <= end:
mid = int(first + (end-first)/2)#避免溢出
if isBadVersion(mid) == True:
if mid-1 <first:
return mid
elif isBadVersion(mid-1) == False:
return mid
else:
end = mid-1
else:
if mid + 1 >=end:
return mid+1
elif isBadVersion(mid+1) == True:
return mid+1
else:
first = mid+1
return -1
35. Search Insert Position
插入在查找的位置之后
s = 0
end = len(nums)-1
while s<=end:
mid = int(s+(end-s)/2)
if nums[mid] == target:
return mid
elif nums[mid] < target:
s = mid+1
else:
end = mid-1
return end+1
Level2.3.4.5 -Two pointers
977. Squares of a Sorted Array
含有正负数的排序list,输出数组平方的排序
方法1: 找到中间,从中间到两头–复杂
# 从中间开始--多一个遍历
# ans = []
# if nums[0]>=0:
# for item in nums:
# ans.append(item**2)
# return ans
# if nums[len(nums)-1] <0:
# for i in range(len(nums)-1,-1,-1):
# ans.append(nums[i]**2)
# return ans
# for i in range(1,len(nums)):
# if nums[i-1]<0 and nums[i]>=0:
# break
# #[-3,-1,0]
# l = i-1 # <0 1
# r = i # >=0 2 3
# while l>=0 and r<len(nums):
# if 0-nums[l] < nums[r]:
# ans.append(nums[l]**2)
# l = l-1
# else:
# ans.append(nums[r]**2)
# r = r+1
# if l >=0:
# for i in range(l,-1,-1):
# ans.append(nums[i]**2)
# elif r <len(nums):
# for i in range(r,len(nums)):
# ans.append(nums[i]**2)
# return ans
方法2: 从两头到中间
##从两头开始,没有复杂的过程
ans =[0]*len(nums)
l = 0
r =len(nums)-1
for i in range(len(nums)-1,-1,-1):
if abs(nums[l]) < abs(nums[r]):
ans[i] = nums[r]**2
r = r-1
else:
ans[i] = nums[l]**2
l = l+1
return ans
189. Rotate Array
把后面的k位数移到前面
方法一: reverse:
全倒序: 7654321
把前k = 3 位 反转: 5674321
把剩下的反转: 5671234
需要自己写反转函数
特殊样例: k可能大于数组长度,要取余处理
if k ==0 or k == len(nums) or len(nums) ==1:
pass
else:
# for i in range(k):
# nums.insert(0,nums[-1])
# nums.pop()
k=k%len(nums) #取余
self.partreverse(nums,0,len(nums)-1)
self.partreverse(nums,0,k-1)
self.partreverse(nums,k,len(nums)-1)
def partreverse(self,nums,left, right):
while left<right:
left_item = nums[left]
nums[left] = nums[right]
nums[right] = left_item
left = left + 1
right = right -1
return nums
法2⃣️:cycling replacement
直接找到数字所在位置
283. Move Zeroes
把前面的0全移到最后
方法一:双指针:一个是遍历位置,一个是结束位置
i = 0
end = len(nums)-1
while i <end:
if nums[i] == 0:
nums.pop(i)
nums.append(0)
end = end-1
else:
i = i+1
167. Two Sum II - Input Array Is Sorted
找到剩下的那一半值
边缘样例:
[0,0,3,4] 0 -> 出现重复
[5,25,75] 100 -> 找不到的话会异常
[-3,3,7,10] 0
[-1,0,3,4] -1
brute force:超时
Two- pointers:
left = 0
right = len(numbers)-1
while left<right:
if numbers[left]+numbers[right] == target:
return [left+1,right+1]
elif numbers[left]+numbers[right] < target:
left = left + 1
else:
right = right-1
dictionary:
dic = {}
for i,val in enumerate(numbers):
if target - val in dic:
return [dic[target - val]+1,i+1]
else:
dic[val] =i
Binary search:
# for i in range(len(numbers)):
# rest = target - numbers[i]
# if rest in numbers:
# index2 = numbers.index(rest)
# if index2!=i:
# if i<index2:
# return [i+1,index2+1]
# else:
# return [index2+1,i+1]
#以上超时,改为二分查找
for i in range(len(numbers)):
rest = target - numbers[i]
l = i+1
r = len(numbers)-1
while l<=r:
mid = l+(r-l)//2
if numbers[mid] == rest:
return [i+1,mid+1]
elif numbers[mid] < rest:
l = mid+1
else:
r = mid-1
344. Reverse String
从两头互相交换
left = 0
right = len(s)-1
while left <right:
s[left],s[right] = s[right],s[left]
left = left +1
right = right -1
557. Reverse Words in a String III
找到空格后反转每个单词
res = ''
l, r = 0, 0
while r < len(s):
if s[r] != ' ':
r += 1
elif s[r] == ' ':
res += s[l:r + 1][::-1]#[::-1]反转
r += 1
l = r
res += ' '
res += s[l:r + 2][::-1]
return res[1:]
876. Middle of the Linked List
找到中间:快慢指针
slow = head
fast = head
while fast.next and fast.next.next:
slow = slow.next
fast = fast.next.next
if fast.next:
return slow.next
else:
return slow
19. Remove Nth Node From End of List
删掉倒数第n个节点:
快慢指针,快指针先走k步,慢指针再走
边界情况:
只有一个节点:输出空
删掉最后一个节点:最后一个节点.next直接改None
删掉第一个节点:当快指针直接到达最后一个节点时,输出删掉头节点的链表
if head .next ==None:#只有一个节点
return None
fast = head
for i in range(n):
fast = fast.next
if not fast: #删掉第一个节点
return head.next
slow = head
while fast .next !=None:
slow = slow.next
fast = fast.next
if n==1: #删掉最后一个节点
slow.next = None
else:
slow.next = slow.next.next
return head
Level 6 -Sliding Window
3. Longest Substring Without Repeating Characters
方法1: 滑动窗口+字典
思路:
- 遍历字符串:不在字典里把字母和位置添到字典里,并更新最长长度
- 出现重复字符:新窗口从重复字符前面那个的后一位开始算
- 继续更新字典:如果值在窗口外面就更新到里面
if len(set(s)) == len(s): return len(s)
dic = {}
maxlen = 0
order = 0
for i,value in enumerate(s):
if value not in dic or dic[value]<order:
dic[value] = i
if maxlen < i-order+1:
maxlen = i-order+1
else:
order = dic[value]+1
dic[value] = i
return maxlen
方法二:滑动窗口+set
出现重复就挪窗口左边一位 -> 不用处理尾部
maxlen = 0
left = 0
for i in range(1,len(s)+1):
if len(set(s[left:i])) == i-left:
if maxlen < i-left:
maxlen = i-left
else:
left = left+1
return maxlen