写个最小堆呗,构建堆时用上浮算法(就是添加于末尾,若小于父节点,交换,直到到根节点为止),堆构建完成后,使用下沉算法,若大于根节点,与它交换,然后判断是否大于下面的值,直到最后一层。父节点 = 子结点-1>>1 子结点 = (父节点<<1)+1 or 前一个节点+1.
class Solution(object):
class heap:
__slots__ = ['k','h','size']
def __init__(self,k):
self.h = []
self.k = k
self.size = 0
def add(self,val):
if self.size<self.k:
self.flow(val)
else:
self.sink(val)
# print self.h
def flow(self,val):
self.h.append(val)
self.size+=1
inx = self.size-1
while inx>0 and self.h[inx-1>>1]>self.h[inx]:
inx_n = inx-1>>1
self.h[inx],self.h[inx_n] = self.h[inx_n],self.h[inx]
inx = inx_n
def sink(self,val):
if val<=self.h[0]:
return
self.h[0] = val
inx =0
while inx<self.k:
inx_n = (inx<<1)+1
if inx_n+1<self.k and self.h[inx_n+1]<self.h[inx_n]:
inx_n += 1
if inx_n<self.k and self.h[inx_n]<self.h[inx]:
self.h[inx],self.h[inx_n] = self.h[inx_n],self.h[inx]
else:
return
inx = inx_n
def findKthLargest(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: int
"""
h = self.heap(k)
for i in nums:
h.add(i)
return h.h[0]
看到logN的时间复杂度估计得二分,但是这玩意也没有顺序呀,不过其实这也不需要顺序,二分的核心思路就是每次扔一半的数呗。
这题只需要存在任意一个峰值即可,如果中间值的左大于它,那么左+中间值,必有峰值存在。但是因为是取左边界,为了避免死循环,取到的数必然是峰值的右一位。
class Solution(object):
def findPeakElement(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
nums = [nums[0]-1]+nums+[nums[0]-1]
left = 1
right = len(nums)-2
while left<right:
mid = left+right>>1
if nums[mid+1]<nums[mid]:
right = mid
else:
left = mid+1
return left-1
二次二分搜索,一次找左边界一次找右边界,
class Solution(object):
def searchRange(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
left = 0
right = len(nums)-1
ans = [-1,-1]
if nums==None or len(nums)==0:
return ans
while left<right:
mid = left+right>>1
if nums[mid]<target:
left = mid+1
else:
right = mid
ans[0] = left if nums[left]==target else -1
left = 0
right = len(nums)-1
while left<right:
mid = left+right+1>>1
if nums[mid]<=target:
left = mid
else:
right = mid-1
ans[1] = left if nums[left]==target else -1
return ans
首先一个左端排序,用一个数组保存结果,然后如果新来的元素,左端点大于右端点,那加一个新的,后面的必然比前一个大,和最后一个比较即可,若小于则合并。
class Solution:
def merge(self, intervals):
if len(intervals)<1:
return intervals
intervals.sort(key=lambda x: x[0])
merged = [intervals[0]]
for interval in intervals[1:]:
if merged[-1][1] < interval[0]:
merged.append(interval)
else:
merged[-1][1] = max(merged[-1][1], interval[1])
return merged
老题了,就是正常判断然后加一波是否包含旋转。
var search = function(nums, target) {
let left = 0,right = nums.length-1
while(left<right){
let mid = left+right>>1
if(nums[mid]==target) {
left = mid;
break;
}
if(target>nums[nums.length-1]){
if(nums[mid]<target&&nums[mid]>nums[nums.length-1])
left = mid+1;
else
right = mid-1;
}else{
if((nums[mid]>target&&nums[mid]<nums[0])||(nums[0]<nums[nums.length-1]&&nums[mid]>target))
right = mid-1;
else
left = mid+1;
}
}
return nums[left]==target?left:-1
};
从左下角找起。
var searchMatrix = function(matrix, target) {
if (!(matrix && matrix.length > 0 && typeof matrix[0][0] === 'number')) {
return false;
}
if (target < matrix[0][0]) {
return false;
}
let row = matrix.length - 1;
let col = 0;
while(col < matrix[0].length && row >= 0) {
if (matrix[row][col] > target) {
row--;
} else if (matrix[row][col] < target) {
col++
} else {
return true;
}
}
return false;
};
这题更像是贪心,每次都一策略,选择当下最远能跳到的范围。
var canJump = function(nums) {
let dis = nums[0];
for(let i=0;i<nums.length-1;++i){
if(nums[i]>nums.length-2)
return true;
dis--;
dis = Math.max(nums[i],dis);
if(dis<=0)
return false;
}
return dis>=0;
};