【LeetCode刷题日常】:双指针

139 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情


前言

双指针基于暴力解法的优化

其指的是利用两个变量在线性结构上遍历,进而可以解决的某些问题。

一般可以用于降低时间复杂度

今天又刷了三道题,分享分享


例1_反转字符串:

🌱题目要求:

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

示例 1:

  • 输入:s = ["h","e","l","l","o"]
  • 输出:["o","l","l","e","h"]

示例 2:

  • 输入:s = ["H","a","n","n","a","h"]
  • 输出:["h","a","n","n","a","H"]

提示:

  • 1 <= s.length <= 105
  • s[i] 都是 ASCII 码表中的可打印字符

💡思路1:

  • 翻转前:[s[0],s[1],s[2] … s[n-1]]
  • 翻转后:[s[n-1],s[n-2],s[n-3] … s[0]]
  • 通过观察,我们得出这道题的解法:
  • 我们定义两个指针ij(或者说是数组的索引)
  • 分别指向数组的首元素末元素
  • 然后两指针边交换元素,边向中间移动
  • i<j时,反转结束,返回数组即可。

🌳代码实现

image.png


例2_轮转数组:


🌱题目要求:

给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

示例 1:

  • 输入: nums = [1,2,3,4,5,6,7], k = 3

  • 输出: [5,6,7,1,2,3,4]

解释:

  • 向右轮转 1 步: [7,1,2,3,4,5,6]

  • 向右轮转 2 步: [6,7,1,2,3,4,5]

  • 向右轮转 3 步: [5,6,7,1,2,3,4]

示例 2:

  • 输入:nums = [-1,-100,3,99], k = 2

  • 输出:[3,99,-1,-100]

解释:

  • 向右轮转 1 步: [99,-1,-100,3]

  • 向右轮转 2 步: [3,99,-1,-100]

提示:

  • 1 <= nums.length <= 105

  • -231 <= nums[i] <= 231 - 1

  • 0 <= k <= 105

💡思路1

  • 首先应该想到,如果k值大于数组长度时,我们应该更新k值,即k%=nums.size()将重复部分去掉。
  • 接着,以题目为例: nums = [1,2,3,4,5,6,7], k = 3
  • 我们先反转一次得到 nums = [7,6,5,4,3,2,1]
  • 把翻转后的数组看作两部分
  • 如:[7,6,5] [4,3,2,1]
  • 再分别翻转
  • 最后就可以得到最终结果[5,6,7,1,2,3,4]

🌳代码实现

image.png

💡思路2

  • 我们新建立一个数组new_arr[],
  • 然后通过for循环遍历原数组nums[]
  • 将原数组的元素nums[i]放到新数组new_arr[(i+k)%n]
  • 最后将new_arr[]中的元素复制到nums[]即可。

🌳代码实现

image.png


例3_移动零

🌱题目要求:

示例 1:

  • 输入: nums = [0, 1, 0, 3, 12]
  • 输出 : [1, 3, 12, 0, 0]

示例 2 :

  • 输入 : nums = [0]
  • 输出 : [0]

提示 :

  • 1 <= nums.length <= 104
  • -231 <= nums[i] <= 231 - 1

💡思路1

  • 题目的要求是:将数组中的零全部移动到末尾,其余数字的顺序不要变
  • 我们定义两个指针ij,分别初始化为0
  • 指针i用来遍历整个nums数组
  • 指针j用来指向处理后的数组
  • 利用while循环,遍历数组nums
  • 循环里面,利用if语句,判断元素nums[i]是否不为零
  • 如果元素是非零值,就将该元素nums[i]赋值给nums[j],同时j指向下一位元素;
  • 接着i++;指向下一个元素
  • 如此反复,直到遍历完整个数组
  • 最后再将nums[j]后面的元素全部赋值为0

🌳代码实现

image.png


💡思路2

  • 我们定义两个指针ij,分别初始化为0
  • 然后利用while循环来遍历数组nums[]
  • 接着利用if语句,判断nums[i]是否不为零
  • 当遇到非零值nums[i]时,就将nums[i]nums[j]交换一下
  • 接着j++指向下一位元素
  • 然后是i++
  • while循环结束后,就已经完成题目要求了

🌳代码实现

image.png

写成动态图是这样的:

移动零展示.gif


好了,三道例题已经看完,你的解题思路是什么那,快来评论区一起讨论吧!