主要介绍的是双指针算法!就是左右两个指针根据某个逻辑移动来达到效果!
首先我们通过第一题来简单的了解双指针到底是神码东西!
27. 移除元素
我们来分析一下题目,目的就是把不是目标值的数据放到数组前面并返回长度!
那怎么利用双指针那?
- 首先我们是不是可以用一个指针来遍历数组,把不是目标值的元素放到一个新的数组里面,那这个数组就是答案啦!
- 但是题目要用
O(1)
的空间复杂度,TMD! - 那我们是不是可以通过上面的指针遍历到不是目标值的数组依次覆盖数组那?那我们就在来一个指针从0开始,只要不是目标元素就覆盖数组,然后指针++即可!
class Solution {
public int removeElement(int[] nums, int val) {
// 慢指针
int slowIndex = 0;
// 快指针
for (int fastIndex = 0; fastIndex < nums.length; fastIndex ++){
if (nums[fastIndex] != val){
nums[slowIndex++] = nums[fastIndex];
}
}
return slowIndex;
}
}
第一题应该是可以说AC啦,那我们准备拿捏下面的题目呗!
26. 删除有序数组中的重复项
这道题目的就是看有几种数据,并把不同的数据放到前面返回长度!
那肯定还是用双指针呀!
- 先来一个指针遍历数组,主要是为啦找到前后不一致的元素
- 再来一个指针当作下标来记录不同元素!
class Solution {
public int removeDuplicates(int[] nums) {
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < nums.length; fastIndex++){
if (nums[fastIndex] != nums[slowIndex]){
nums[++slowIndex] = nums[fastIndex];
}
}
return slowIndex + 1;
}
}
第三题来啦,如果还没有熟悉那我们再来一道题!
283. 移动零
其实这道题目和第一题很像,只不过目标值已经告诉我们啦,就是0嘛!
那我们来想一下怎么用双指针那?
- 先来个指针遍历数组,主要找不是目标值的元素
- 因为我们需要把0移动到末尾,所以说我们不能像第一题一样,直接覆盖,需要再来一个指针从头开始把不是目标值的数据全部交换到前面,那剩下不就是0来嘛!
class Solution {
public void moveZeroes(int[] nums) {
// 双指针算法
int target = 0;
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < nums.length; fastIndex ++){
if (nums[fastIndex] != target){
swap(nums, slowIndex, fastIndex);
slowIndex ++;
}
}
}
public void swap(int[] nums, int slowIndex, int fastIndex){
int tmp = nums[slowIndex];
nums[slowIndex] = nums[fastIndex];
nums[fastIndex] = tmp;
}
}
兄弟们,再接再厉啊!就剩两道题啦!(悄悄的告诉你们,我不是连续做的,也是花来好几天才把这些昨晚,咱们可以**点赞收藏关注**,回头接着看!!!)
这道题目就非常的恶心啦,第一次看题目的时候没看懂,到底是干啥那!好想喷描述的人!后来真是在下愚昧啦,它的意思就是碰见#
就是相当于Backspace
退格键,把前面的字母删除来就行!然后来比较两个字符串是否相等!TMD!
那么这道题怎么整那?
- 我们可以像做第一题的时候一样,
#
作为目标元素,然后通过慢指针进行记录非目标元素 - 虽然可以用第一题的双指针做法做,但是有退格怎么办?其实遇到退格之后,慢指针的上一个存储的元素删除啦不就ok啦!
class Solution {
public boolean backspaceCompare(String s, String t) {
String[] sArr = s.split("");
String[] tArr = t.split("");
String target = "#";
// 把退格后的结果放到slowIndex前面
int sSlowIndex = doubleIndex(sArr, target);
int tSlowIndex = doubleIndex(tArr, target);
s = t = "";
// 拼接字符串
for(int i = 0; i < sSlowIndex; i ++){
s += sArr[i];
}
for(int i = 0; i < tSlowIndex; i ++){
t += tArr[i];
}
// 比较字符串
if (s.substring(0,sSlowIndex).equals(t.substring(0, tSlowIndex)) == true){
return true;
}
return false;
}
public int doubleIndex(String[] arr, String target){
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < arr.length; fastIndex ++){
if (arr[fastIndex].equals(target) == false){
arr[slowIndex++] = arr[fastIndex];
}else{
// 全文精华,退格不就是把慢指针的上一个元素删除来嘛!
if (slowIndex != 0){
slowIndex = slowIndex - 1;
}
}
}
return slowIndex;
}
}
最后一道题目啦,朋友们,你确定不加个关注,点个赞嘛!弟弟也想上热门呀!给弟弟点动力!
977. 有序数组的平方
题目的目的就是排序嘛,我们可以先平方然后再用快排或者其他排序算法来解决问题,但是我们今天得 点题嘛,双指针也可以哦!
- 因为给的数组是有序的,因为有正负,所以比较难搞!但是针对正负这种,顺序无非就是最左端或者最右端嘛!
- 那我们左边一个指针,右边一个指针,然后平方后谁大就放到最后面,依次遍历,知道左右指针重合
class Solution {
public int[] sortedSquares(int[] nums) {
int left = 0;
int right = nums.length - 1;
int index = nums.length - 1;
int[] result = new int[nums.length] ;
while (left <= right){
if (nums[left] * nums[left] < nums[right] * nums[right]){
result[index--] = nums[right] * nums[right];
right --;
}else{
result[index--] = nums[left] * nums[left];
left ++;
}
}
return result;
}
}
总结一下,我们主要聊的双指针算法,我们回忆上面的解法,刚开始就是拿一个快指针遍历数组来找非目标值,再来个一个慢指针依次记录结果!后来不能覆盖原数组啦,需要把目标值放到最后,那我们交换一下就行!后来又玩退格,其实就是把慢指针的上一个值覆盖就行!最后的最后两个指针不从一边走啦,从两个方向玩啦!
这个双指针呀,真的是玩的花啊!
那一般什么时候用双指针那?
据我分析一看到元素有序基本上就可以考虑双指针来!
感谢大家的阅读,我是Alson_Code🆒,一个喜欢把简单问题复杂化,把复杂问题简单化的程序猿! ❤