Day01-1119刷题:数组–704. 二分查找,27. 移除元素,977. 有序数组的平方,209. 长度最小的子数组
| 题目 | 用时 |
|---|---|
| 704.二分查找 | 14m51s |
| 27. 移除元素 | 5m54s |
| 977. 有序数组的平方 | 17m12s |
| 209. 长度最小的子数组 | 30m |
704.二分查找
[!NOTE]
给定一个
n个元素有序的(升序)整型数组nums和一个目标值target,写一个函数搜索nums中的target,如果target存在返回下标,否则返回-1。你必须编写一个具有
O(log n)时间复杂度的算法。
首次写没有注意到循环结束条件,模糊了左闭右闭和左闭右开的区别;其次,将return -1写到了while循环的else中,导致出现超时;
class Solution(object):
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
length = len(nums)
left,right = 0, length - 1
while left <= right:
if target < nums[(left + right)/2]:
right = (left + right)/2 - 1
elif target > nums[(left + right)/2]:
left = (left + right)/2 + 1
elif target == nums[(left + right)/2]:
return (left + right)/2
return -1
[!TIP]
用
mid = (left + right)/2来统一表示, 且最好用(left + right) / 2避免溢出
27.移除元素
[!NOTE]
给你一个数组
nums和一个值val,你需要 原地 移除所有数值等于val的元素。元素的顺序可能发生改变。然后返回nums中与val不同的元素的数量。假设
nums中不等于val的元素数量为k,要通过此题,您需要执行以下操作:
- 更改
nums数组,使nums的前k个元素包含不等于val的元素。nums的其余元素和nums的大小并不重要。- 返回
k。
这题之前在labuladong的双指针技巧中有学到,原地移除限制了不能遍历数组将不等于 val 的值移动到新数组中,也就是说遇到 nums[i] == val 的情况时,我需要直接修改 nums[i] 的值,直接的想法是双循环,外层寻找nums[i] == val ,内层负责更新数组(将所有i以后的前移一位),为了减少一层循环则可以用到快慢指针,将慢指针内的值定为存储非val值,当快指针遇到val时,则跳过将这个值存储到慢指针的前k个区域内
class Solution(object):
def removeElement(self, nums, val):
"""
:type nums: List[int]
:type val: int
:rtype: int
"""
fast, slow = 0, 0
while fast < len(nums):
if nums[fast] != val:
nums[slow] = nums[fast]
slow += 1
fast += 1
nums = nums[:slow]
return slow
977.有序数组的平方
[!NOTE]
给你一个按 非递减顺序 排序的整数数组
nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
最开始想的直接用平方后的结果sort一下就好了,时间复杂度是 O(n + nlogn);
后续考虑到用左右指针的方法,先将数组进行平方,再将左右比较,大的先加进数组,然后缩小再比较,最后用 reverse(),时间复杂度是 O(n + n + n);
最终考虑直接将大的加入到结果数组的末尾(减少reverse的操作)
class Solution(object):
def sortedSquares(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
# square = [i**2 for i in nums]
left, right = 0, len(nums) - 1
sorted_square = [0] * len(nums)
i = len(nums) - 1
while left <= right:
if nums[left]**2 < nums[right]**2:
sorted_square[i] = nums[right]**2
right -= 1
i -= 1
else:
sorted_square[i] = nums[left]**2
left += 1
i -= 1
return sorted_square
209. 长度最小的子数组
[!NOTE]
给定一个含有
n个正整数的数组和一个正整数target。找出该数组中满足其总和大于等于
target的长度最小的 子数组[numsl, numsl+1, ..., numsr-1, numsr],并返回其长度**。**如果不存在符合条件的子数组,返回0。
想要用滑动窗口解决问题,小了则右边扩大,大了则左边缩小
class Solution(object):
def minSubArrayLen(self, target, nums):
"""
:type target: int
:type nums: List[int]
:rtype: int
"""
fast, slow = 0, 0
min_length = len(nums) + 1
if sum(nums) < target:
return 0
while fast <= len(nums) - 1:
if sum(nums[slow:fast + 1]) < target:
fast += 1
elif sum(nums[slow:fast + 1]) >= target:
length = fast - slow + 1
if length < min_length:
min_length = length
slow += 1
return min_length
这样写是错误的,因为不断在计算sum(nums[slow:fast + 1]),因此优化了一下,用一个数组暂存值的和,再进行加减,这样的话就需要在判断sum>target的时候用上while来进行窗口的持续移动
class Solution:
def minSubArrayLen(self, s, nums):
l = len(nums)
left = 0
right = 0
min_len = float('inf')
cur_sum = 0 #当前的累加值
while right < l:
cur_sum += nums[right]
while cur_sum >= s: # 当前累加值大于目标值
min_len = min(min_len, right - left + 1)
cur_sum -= nums[left]
left += 1
right += 1
return min_len if min_len != float('inf') else 0
[!TIP]
这题卡了很久,最开始就想到了用滑动窗口解决这个问题,在第一版中由于不断多次的计算
sum(nums[slow:fast + 1])而导致超时问题,考虑用数组暂存后又忽略了每次外循环时会重复加上nums[right]的值

811

被折叠的 条评论
为什么被折叠?



