Leetcode刷题总结——数组

数组是存放在连续内存空间上的相同类型数据的集合。

  • 数组下标都是从0开始的。
  • 数组内存空间的地址是连续的

因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。

数组的元素是不能删的,只能覆盖。

一、二分查找

这道题目的前提是数组为有序数组,同时题目还强调数组中无重复元素,因为一旦有重复元素,使用二分查找法返回的元素下标可能不是唯一的,这些都是使用二分法的前提条件。

二分法逻辑比较简单,但容易写乱,比如是while(left循环不变量规则。

写二分法,区间的定义一般可以分为两种,左闭右闭[left,right],或者左闭右开[left,right)。

(以下解答均基于题目704)

二分法第一种写法

第一种写法,我们定义 target 是在一个在左闭右闭的区间里,也就是[left, right]

区间的定义这就决定了二分法的应该如何写,因为定义target在[left, right]区间,所以有如下两点:

1)while(left<=right)要使用<=,因为left==right是有意义的,所以使用<=;

2)if(nums[mid]>target) right要赋值为mid-1,因为当前这个nums[mid]一定不是target,那么接下来要查找的左区间结束下标位置就是mid-1。

二分法第二种写法

如果说定义 target 是在一个在左闭右开的区间里,也就是[left, right) ,那么二分法的边界处理方式则截然不同。

有如下两点:

1)while(left

2)if(nums[mid]>target) right更新为mid,因为当前这个nums[mid]不等于target,去左区间继续寻找,而寻找的左区间是左闭右开区间,所以right更新为mid,即下一个查询区间不会去比较nums[mid]。

1、

Leetcode刷题总结——数组_第1张图片

法一:

Leetcode刷题总结——数组_第2张图片

法二:

Leetcode刷题总结——数组_第3张图片 

2、

Leetcode刷题总结——数组_第4张图片

Leetcode刷题总结——数组_第5张图片

 3、

Leetcode刷题总结——数组_第6张图片

寻找target在数组里的左右边界,有如下三种情况:

  • 情况一:target 在数组范围的右边或者左边,例如数组{3, 4, 5},target为2或者数组{3, 4, 5},target为6,此时应该返回{-1, -1}
  • 情况二:target 在数组范围中,且数组中不存在target,例如数组{3,6,7},target为5,此时应该返回{-1, -1}
  • 情况三:target 在数组范围中,且数组中存在target,例如数组{3,6,7},target为6,此时应该返回{1, 1}

所以可以写两个二分去分别寻找左右边界。

寻找右边界:

Leetcode刷题总结——数组_第7张图片

 寻找左边界:

Leetcode刷题总结——数组_第8张图片

最终代码:

Leetcode刷题总结——数组_第9张图片

Leetcode刷题总结——数组_第10张图片

Leetcode刷题总结——数组_第11张图片

4、 

Leetcode刷题总结——数组_第12张图片

Leetcode刷题总结——数组_第13张图片

 二、移/除元素

数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。

1、

Leetcode刷题总结——数组_第14张图片

Leetcode刷题总结——数组_第15张图片

双指针法快慢指针法

Leetcode刷题总结——数组_第16张图片

2、 

 Leetcode刷题总结——数组_第17张图片

 Leetcode刷题总结——数组_第18张图片

Leetcode刷题总结——数组_第19张图片

3、

 Leetcode刷题总结——数组_第20张图片

Leetcode刷题总结——数组_第21张图片

4、

Leetcode刷题总结——数组_第22张图片

方法一:(使用栈的思路)栈适用于做匹配问题

Leetcode刷题总结——数组_第23张图片

 方法二:双指针

 Leetcode刷题总结——数组_第24张图片

 5、

Leetcode刷题总结——数组_第25张图片

方法一:(sort排序 时间复杂度为 O(nlogn))

方法二:(归并排序后双指针)

负数部分,平方以后单调递减,大于等于0的部分,平方以后单调递增

首先找到负数结束的位置记为 neg,使用两个指针分别指向位置 neg 和 neg+1,每次比较两个指针对应的数,选择较小的那个放入答案并移动指针。当某一指针移至边界时,将另一指针还未遍历到的数依次放入答案。

Leetcode刷题总结——数组_第26张图片

方法三:直接双指针

使用两个指针分别指向位置 00 和 n-1n−1,每次比较两个指针对应的数,选择较大的那个逆序放入答案并移动指针。这种方法无需处理某一指针移动至边界的情况。

Leetcode刷题总结——数组_第27张图片

 三、关于数组中的连续问题(滑动窗口)

1、

Leetcode刷题总结——数组_第28张图片

方法一:暴力法

Leetcode刷题总结——数组_第29张图片

方法二:滑动窗口

Leetcode刷题总结——数组_第30张图片

2、

Leetcode刷题总结——数组_第31张图片

Leetcode刷题总结——数组_第32张图片

题目可以理解为求只包含两种元素的最长连续子序列

 Leetcode刷题总结——数组_第33张图片

 3、

Leetcode刷题总结——数组_第34张图片

解题思路:

1)用一个哈希表mpt先存放字符串t中的字符

2)定义两个指针 start和end,start指针用于收缩窗口,end指针用于延伸窗口,区间[start,end]表示当前滑动窗口。首先让start,end指针都指向字符串s开头,然后枚举整个字符串s,在枚举过程中,不断增加end,使滑动窗口增大。在窗口变大的同时,需要记录加入的字符数,即mps[s[end]]++

3)对于新加入的字符s[start],如果mps[s[start]]<=mpt[s[start]],说明当前新加入的字符s[start]是必须的,而且未达到字符串t所要求的数量。其次我们还需要事先定义一个cnt变量,cnt维护的是s字符串[start,end]区间中满足t字符串的元素的个数,记录相对字符的总数。如果新加入的字符s[start]必需,则cnt++

4)向右扩展滑动窗口的同时还需要收缩窗口,当mps[s[start]]>mpt[s[start]]时,说明mps哈希表中s[start]的数量多于mpt哈希表中s[start]的数量,此时我们就需要向右收缩滑动窗口,mps[s[start]]--并使,start++

5)当cnt==t.size()时,说明此时滑动窗口包含字符串t的全部字符。重复上述过程找到最小窗口即可

Leetcode刷题总结——数组_第35张图片

四、螺旋矩阵问题

主要遵循 循环不变量问题

1、

Leetcode刷题总结——数组_第36张图片

Leetcode刷题总结——数组_第37张图片

Leetcode刷题总结——数组_第38张图片

 2、

Leetcode刷题总结——数组_第39张图片

方法一:

初始位置为矩阵的左上角,初始方向是向右,当路径超出界限或者进入之前已经访问过的位置时,顺时针旋转,进入下一个方向。

因此需要引入一个与输入矩阵大小相同的辅助矩阵visited,记录每个位置是否被访问过。

由于矩阵中的每个元素都被访问一次,因此路径的长度即为矩阵中的元素数量,当路径的长度达到矩阵中的元素数量时即为完整路径,将该路径返回。

Leetcode刷题总结——数组_第40张图片 方法二:

一层一层向内圈遍历

Leetcode刷题总结——数组_第41张图片

 Leetcode刷题总结——数组_第42张图片

(第二种更清晰)

 Leetcode刷题总结——数组_第43张图片

你可能感兴趣的:(C++刷题笔记,leetcode,算法)