1、leetcode35 二分,很简单
class Solution(object):
def searchInsert(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
l = len(nums)
start = 0
end = l-1
while start<=end:
mid = int((start+end)/2)
if target > nums[mid]:
start = mid+1
elif target< nums[mid]:
end = mid-1
elif target == nums[mid]:
return mid
nums.insert(start,target)
return start
2、leetcode34
class Solution(object):
def searchRange(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
start = 0
end = len(nums)-1
self.res = [end+1,-1]
self.helper(nums,start,end,target)
if self.res[0] == end+1 and self.res[1]==-1:
return [-1,-1]
return self.res
def helper(self,nums,start,end,target):
if start > end:
return False
mid = int((start+end)/2)
if target > nums[mid]:
self.helper(nums,mid+1,end,target)
elif target < nums[mid]:
self.helper(nums,start,mid-1,target)
elif target == nums[mid]:
if mid < self.res[0] :
self.res[0]= mid
if mid >self.res[1]:
self.res[1]= mid
self.helper(nums,start,mid-1,target)
self.helper(nums,mid+1,end,target)
我用的是纯递归+二分,看了评论可以写个遍历+递归,或者是通过写两个二分,通过找区间的左右端点来加快。
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
res=[-1,-1]
res[0]=self.findleft(nums,0,len(nums)-1,target)
res[1]=self.findright(nums,0,len(nums)-1,target)
return res
def findleft(self,nums,start,end,target):
while start<=end:
mid = int((start+end)/2)
if target > nums[mid]:
start = mid +1
elif target < nums[mid]:
end =mid-1
elif target == nums[mid]:
if mid ==0 or nums[mid-1]<target:
return mid
else:
end = mid -1
return -1
def findright(self,nums,start,end,target):
while start<=end:
mid = int((start+end)/2)
if target > nums[mid]:
start = mid +1
elif target < nums[mid]:
end =mid-1
elif target == nums[mid]:
if mid ==len(nums)-1 or nums[mid+1]>target:
return mid
else:
start = mid +1
return -1
效率比较:
3、leetcode33
class Solution(object):
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
if len(nums)==0:
return -1
start = 0
end = len(nums)-1
if target>nums[end]:
if target<nums[0]:
return -1
for i in range(len(nums)-1):
if target == nums[i]:
return i
if nums[i]>nums[i+1]:
return -1
break
return -1
if target <nums[end]:
i = end
while i>=0:
if target == nums[i]:
return i
if nums[i]<nums[i-1]:
return -1
i -=1
return -1
if target == nums[end]:
return end
用时居然击败了96%。。。。感觉就是暴力+一一点点分类,换了一种分前半部分和后半部分有序无序的二分方法写
class Solution(object):
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
if len(nums)==0:
return -1
start = 0
end = len(nums)-1
while start<=end:
mid = int((start+end)/2)
if nums[mid]==nums[start]:
for i in range(start,end+1):
if target == nums[i]:
return i
return -1
if nums[mid]<nums[start]: #前半部分无序,后半部分有序
idx = self.findidx(nums,mid,end,target)
print(idx)
if idx!=-1:
return idx
end = mid-1
if nums[mid]>nums[start]:
idx = self.findidx(nums,start,mid,target)
if idx!=-1:
return idx
start = mid
return -1
def findidx(self,nums,start,end,target):
while start<=end:
mid = int((start+end)/2)
print(start,end,mid)
if target == nums[mid]:
return mid
if target < nums[mid]:
end = mid-1
if target > nums[mid]:
start = mid+1
return -1
归并排序
class Solution(object):
def countSmaller(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
self.mergesort(nums,0,len(nums)-1)
return nums
def mergesort(self,nums,start,end):
if start<end:
mid = int((start+end)/2)
self.mergesort(nums,start,mid)
self.mergesort(nums,mid+1,end)
self.merge(nums,start,mid+1,end+1)
else:
return
def merge(self,nums,start,mid,end):
i = start
j = mid
s=[]
while i < mid and j < end:
#print(nums[i],nums[j])
if nums[i]>nums[j]:
s.append(nums[j])
j +=1
else:
s.append(nums[i])
i +=1
while i <mid:
s.append(nums[i])
i +=1
while j < end:
s.append(nums[j])
j +=1
k=0
for i in range(start,end): #更新从start到end区域的nums
nums[i] = s[k]
k+=1
归并排序的思想就是分治,将问题分解为多个相互独立、性质相同的子问题。时间复杂度为ONlogN,可根据这一思想解决一些问题。
4、leetcode315
给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量。
示例:
输入: [5,2,6,1]
输出: [2,1,1,0]
class Solution(object):
def countSmaller(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
self.count=[0 for i in range(len(nums))]
res=[]
for i in range(len(nums)):
t = (nums[i],i)
res.append(t)
self.mergesort(res,0,len(nums)-1)
return self.count
def mergesort(self,nums,start,end):
if start<end:
mid = int((start+end)/2)
self.mergesort(nums,start,mid)
self.mergesort(nums,mid+1,end)
self.merge(nums,start,mid+1,end+1)
else:
return
def merge(self,nums,start,mid,end):
i = start
j = mid
s=[]
while i < mid and j < end:
if nums[i]<=nums[j]:
s.append(nums[i])
self.count[nums[i][1]]+=j-mid
i +=1
else:
s.append(nums[j])
j +=1
while i <mid:
s.append(nums[i])
self.count[nums[i][1]]+=j-mid
i +=1
while j < end:
s.append(nums[j])
j +=1
#print(self.count)
k=0
for i in range(start,end):
nums[i] = s[k]
k+=1
- 这个题用归并做的,思想是在归并中加入tuple(value,index),之后对tuple比较
- 其中比较重要的merge函数的编写,merge函数最重要的是什么时候更新count,即当前一部分i列表的元素大于后一部分j列表元素时,此时j所指的位置之前所有的位置均小于当前i列表中元素,将j更新到count[i]中去。
5、合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def mergeKLists(self, lists):
"""
:type lists: List[ListNode]
:rtype: ListNode
"""
if len(lists)==0:
return None
if len(lists)==1:
return lists[0]
if len(lists) == 2:
return self.merge(lists[0],lists[1])
mid = int((len(lists)-1)/2)
return self.merge(self.mergeKLists(lists[:mid+1]),self.mergeKLists(lists[mid+1:]))
def merge(self,l1,l2):
head = ListNode(-1)
p = head
while l1 and l2:
if l1.val<=l2.val:
head.next = l1
head = head.next
l1 = l1.next
else:
head.next = l2
head = head.next
l2 = l2.next
if l1:
head.next = l1
head = head.next
l1 = l1.next
if l2:
head.next = l2
head = head.next
l2 = l2.next
return p.next
用归并,复杂度O(logK*KN)