34、48、40、41、189、217,219
34:在排序数组中查找元素的第一个和最后一个位置
题目描述:
给定一个按照升序排列的整数数组 nums,和一个目标值 target,找出给定目标值在数组中的开始位置和结束位置。
思路:
先使用一次二分查找求得target出现的一个位置记录为middle,如果未找到即可直接返回[-1, -1];找到之后,然后进行左逼近找目标值的开始位置;右逼近寻找目标值结束的位置。
左逼进的起始区间开始值为第一次二分查找后的begin的值,结束值为middle - 1,由于左逼近区间的所有值一定是小于等于目标值的,所以在做左逼进区间上做二分查找时每次遇到中间值等于目标值时,将区间的右界限缩小。其他情况一律将左界限增大。
右逼进的起始区间开始值为middle + 1,结束值为数组长度 - 1。由于右逼近区间的所有值一定是大于等于目标值的,所以在做右逼进区间上二分查找时每次遇到中间值等于目标值时,将区间的左界限增大。其他情况一律将右界限缩小。
代码:
class Solution(object):
def searchRange(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
l = 0
r = len(nums) - 1
while l <= r:
mid = (l + r) // 2
if nums[mid] == target:
l = mid
r = mid
while l > 0 and nums[l - 1] == target:
l -= 1
while r < len(nums) - 1 and nums[r + 1] == target:
r += 1
return [l, r]
elif nums[mid] < target:
l = mid + 1
else:
r = mid - 1
return [-1, -1]
48:旋转图像
题目描述:
给定一个 n × n 的二维矩阵表示一个图像。将图像顺时针旋转 90 度。
思路:
先转置矩阵,然后翻转每一行
代码:
for i in range(len(matrix)):
for j in range(i):
matrix[i][j],matrix[j][i]=matrix[j][i],matrix[i][j]
for i in range(len(matrix)):
for j in range(len(matrix[i])//2):
matrix[i][j],matrix[i][len(matrix)-1-j]=matrix[i][len(matrix)-1-j],matrix[i][j]
40:组合总和Ⅱ
题目描述:
给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。candidates 中的每个数字在每个组合中只能使用一次。
思路:
遍历数组中的值,如果nums[i] < target , 尝试把nums[i]作为一个加数,把目标值减去nums[i],下一次递归从i+1开始遍历数组寻找下一个加数
如果target=0,说明找到了一组加数
否则把上一个加数从list中去掉
去重:需要先对数组进行排序,每次递归寻找的是一个位置的加数值,同一个位置不能使用相同的加数值
class Solution(object):
def combinationSum2(self, candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
"""
candidates.sort()
b=[]
def temp(a,d,c):
if d in c:
b.append(a+[d])
if d>c[0]:
for i in range(len(c)):
if i>=1 and c[i]==c[i-1]:
continue
if i+1<len(c):
temp(a+[c[i]],d-c[i],c[i+1:])
temp([],target,candidates)
return b
41:缺失的第一个正数
题目描述:
给定一个未排序的整数数组,找出其中没有出现的最小的正整数
思路:
将数据放到他本来应该在的位置,即nums[i]=i+1,遍历数组,如果哪个位置nums[i]!=i+1,则他就是缺失的数。
代码:
class Solution(object):
def firstMissingPositive(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
size=len(nums)
for i in range(size):
while 1<=nums[i]<=size and nums[i]!=nums[nums[i]-1]:
self.__swap(nums,i,nums[i]-1)
for i in range(size):
if i+1!=nums[i]:
return i+1
return size+1
def __swap(self,nums,index1,index2):
nums[index1],nums[index2]=nums[index2],nums[index1]
189:旋转数组
题目描述:
给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
思路:
代码:
class Solution(object):
def rotate(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: None Do not return anything, modify nums in-place instead.
"""
a=len(nums)
k=k%a
def swap(l,r):
while l<=r:
nums[l],nums[r]=nums[r],nums[l]
r-=1
l+=1
swap(0,len(nums)-k-1)
swap(len(nums)-k,len(nums)-1)
swap(0,len(nums)-1)
217:存在重复元素
题目描述:
给定一个整数数组,判断是否存在重复元素。
思路:
先排序,然后从前遍历相邻元素只要相等就返回true
代码:
class Solution(object):
def containsDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
if len(nums) <= 1:
return False
nums.sort()
j = 0
while j < len(nums) - 1:
if nums[j] == nums[j + 1]:
return True
else:
j += 1
return False
219:存在重复元素Ⅱ
题目描述:
给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,得 nums [i] = nums [j],并且 i 和 j 的差的绝对值最大为 k。
思路:
在散列表中搜索当前元素,如果找到了就返回 true
在散列表中插入当前元素
如果当前散列表的大小超过了 kkk, 删除散列表中最旧的元素,将索引更新为当前索引
代码:
class Solution(object):
def containsNearbyDuplicate(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: bool
"""
hash = {}
for i in range(len(nums)):
if nums[i] not in hash:
hash[nums[i]] = i
else:
if i - hash[nums[i]] <= k:
return True
else:
hash[nums[i]] = i
return False