1、数组
概念:数组是存放在连续内存空间上的相同数据类型的集合。
要查找数组里的数据一般通过查找数据的下标索引的方式来查找。需要注意的是:数组的下标都是从0开始的,并且数组内的元素的存储空间都是连续的。
由于数组的这个特性,所以数组删除或添加元素的时候,不能直接进行删除操作。在增加或删除元素的时候,需要通过移动其他元素的地址来达到目的。
目录
1.1 二分查找
代码随想录公开课视频链接:https://www.bilibili.com/video/BV1fA4y1o715/?vd_source=2b9622026dcb841a7871324bc80f8e61
力扣704题:二分查找 https://leetcode.cn/problems/binary-search/
给定一个 n
个元素有序的(升序)整型数组 nums
和一个目标值 target
,写一个函数搜索 nums
中的 target
,如果目标值存在返回下标,否则返回 -1
。
测试用例:
输入:nums = [-1,0,3,5,9,12]
输出:4
解释:9 出现在nums中并且下标为4
解题思路:
首先,使用二分法的前提条件:数组是有序数组,数组中还需要没有重复元素。(不是必须要满足这两条件,但是满足这两个条件二分查找的结果会更准确。因为一旦数组中有重复元素,那么使用二分查找法返回的元素下标可能就不是唯一的了)。
其次,二分查找的难点在于确定边界条件。二分查找有两个常用的版本。while(left < right)和while(left <= right)都有人写。而这两个写法的区别就在于边界条件不一样,前者对应左闭右闭区间,后者对应左闭右开区间。
以下代码写的是左闭右闭区间版本。
class Solution(object):
def search(self, nums, target):
length = len(nums)
left = 0
right = length - 1
while left <= right :
mid = (left + right) // 2
if nums[mid] < target:
left = mid + 1
elif nums[mid] > target:
right = mid - 1
else:
return mid
return -1
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
类似题目推荐:
力扣35 https://leetcode.cn/problems/search-insert-position/description/
力扣34 https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/description/
力扣69 https://leetcode.cn/problems/sqrtx/description/
力扣367 https://leetcode.cn/problems/valid-perfect-square/description/
目录
1.2 移除元素
代码随想录公开课视频链接:https://www.bilibili.com/video/BV12A4y1Z7LP/?vd_source=2b9622026dcb841a7871324bc80f8e61
力扣27题:https://leetcode.cn/problems/remove-element/description/
给你一个数组 nums
和一个值 val
,你需要 原地 移除所有数值等于 val
的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1)
额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
测试用例:
输入:nums = [3,2,2,3] , val = 3
输出:2,nums = [2,2]
解题思路:
上文我们说过,从数组中删除或添加一个元素不能直接操作,也就是不能单独删除数组中的某个元素,只能采用覆盖的方式。
这类型题目中有个经典的“双指针法”。
双指针法,也叫快慢指针法,该方法的实质就是通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。(该方法在数组和链表的操作中很常见,很多面试题都会使用到该方法,所以要领悟到这个方法的精髓。)
- 快指针:用来遍历数组,寻找要留下来的元素
- 慢指针:用来标记留下来元素的下标
本题代码如下:
class Solution(object):
def removeElement(self, nums, val):
slow = 0
for fast in range(len(nums)):
if nums[fast] != val:
nums[slow] = nums[fast]
slow += 1
return slow
"""
:type nums: List[int]
:type val: int
:rtype: int
"""
类似题目推荐:
力扣26 https://leetcode.cn/problems/remove-duplicates-from-sorted-array/description/
力扣283 https://leetcode.cn/problems/move-zeroes/description/
力扣844 https://leetcode.cn/problems/backspace-string-compare/description/
力扣977https://leetcode.cn/problems/squares-of-a-sorted-array/description/
1.3 有序数组的平方
代码随想录公开课视频链接:双指针法经典题目 | LeetCode:977.有序数组的平方_哔哩哔哩_bilibili
力扣977 977. 有序数组的平方 - 力扣(LeetCode)
给你一个按 非递减顺序 排序的整数数组 nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
测试用例:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解题思路:
从题目描述中,我们可以知道其实给出的数组是有序的。也就是说,数组里的元素平方之后最大值要不就是最左边的元素要不就是最右边的元素,不可能会是中间的元素。所以这时候我们就很自然的想到,用两个指针分别指向数组的起始位置和终止位置。
然后再定义一个空数组用来放置最终结果就行了。这里有个技巧,这个新数组的大小应该和原数组一样大,并且放数的时候应该从最后一个开始放,因为我们是先放大的数。
以下是本题的代码:
class Solution(object):
def sortedSquares(self, nums):
result = [0] * (len(nums))
left = 0
right = len(nums) - 1
for i in range(len(result)-1,-1,-1):
if nums[left] *nums[left] > nums[right] * nums[right]:
result[i] = nums[left] * nums[left]
left += 1
else:
result[i] = nums[right] * nums[right]
right -= 1
return result
1.4 长度最小的子数组
代码随想录公开课视频链接:
拿下滑动窗口! | LeetCode 209 长度最小的子数组_哔哩哔哩_bilibili
力扣209 209. 长度最小的子数组 - 力扣(LeetCode)
给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其总和大于等于 target
的长度最小的 连续子数组
[numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回 0
。
测试用例:
输入:target = 7,nums = [2,3,1,2,4,3]
输出:2
解题思路:
本题采用的解法是数组操作中另一个重要的方法:滑动窗口。
滑动窗口,就是不断调节子序列的起始位置和终止位置,从而得出我们想要的结果。
在这个方法中,我们只采用一个for循环,这个循环的索引表示的是滑动窗口的终止位置。
假设我们要找的是长度为s的连续子数组。那么当窗口的长度已经比s要长了,这个时候我们就该移动我们的窗口了,这时候移动的是窗口的起始位置。那么对于结束位置,只要等for循环完成遍历,它就会自动移动了。
以下是本题的代码:
class Solution(object):
def minSubArrayLen(self, target, nums):
i = 0
sum = 0
lenght = len(nums)
result = lenght + 1
for j in range(len(nums)):
sum += nums[j]
while sum >= target:
s_lenght = j - i + 1
result = min(result,s_lenght)
sum = sum - nums[i]
i += 1
if result == lenght + 1:
return 0
else:
return result
"""
:type target: int
:type nums: List[int]
:rtype: int
"""
类似题目推荐:
力扣904 904. 水果成篮 - 力扣(LeetCode)
力扣76 76. 最小覆盖子串 - 力扣(LeetCode)
1.5 螺旋矩阵
代码随想录公开课视频链接:
一入循环深似海 | LeetCode:59.螺旋矩阵II_哔哩哔哩_bilibili
力扣59 螺旋矩阵II 59. 螺旋矩阵 II - 力扣(LeetCode)
给你一个正整数 n
,生成一个包含 1
到 n2
所有元素,且元素按顺时针顺序螺旋排列的 n x n
正方形矩阵 matrix
。
测试用例:
输入: n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
解题思路:
这道题其实不涉及什么算法内容,主要考察的是对代码实现模拟过程的掌握。
主要是要掌握边界条件:先处理上边界,再处理右边界,然后是下边界,最后是左边界。
以下是本题的代码:
class Solution(object):
def generateMatrix(self, n):
left = 0
right = n - 1
top = 0
bottom = n - 1
num = 1
matrix = [[0] * n for _ in range(n)]
while num <= n ** 2:
for i in range(left, right+1):
matrix[top][i] = num
num += 1
for j in range(top+1, bottom+1):
matrix[j][right] = num
num += 1
if top != bottom:
for a in range(right-1, left-1, -1):
matrix[bottom][a] = num
num += 1
if left != right:
for b in range(bottom-1, top, -1):
matrix[b][left] = num
num += 1
left += 1
right -= 1
top += 1
bottom -= 1
return matrix
类似题目推荐:
力扣54 https://leetcode.cn/problems/spiral-matrix/
(注:本篇内容参考代码随想录~)