指针与双指针的通俗解释

一、指针:内存的“快递单号”

指针可以理解为数据的地址标签,就像快递单号对应包裹的位置一样。在程序中,指针是一个变量,存储的是其他数据在内存中的具体位置(地址),而不是数据本身的值。 

原理: 

  假设内存是一个超大的仓库,每个小格子(字节)都有唯一的编号(地址)。指针就是记录某个格子的编号,通过这个编号可以直接找到对应位置的数据。例如,`int *p = &a;`表示指针`p`记录了变量`a`在内存中的“门牌号”。 

用途: 

  通过指针可以直接操作内存中的数据,比如修改值、传递大型数据(避免复制整个数据)或动态分配内存(灵活管理仓库空间)。

二、双指针:两人协作的“高效工作法”

双指针是用两个指针变量协同解决问题的技巧,通过不同的移动规则优化算法效率。以下是三种常见类型:

1. 快慢指针(龟兔赛跑)

原理: 

两个指针从同一位置出发,速度不同。例如,快指针每次走两步,慢指针走一步。 

应用: 

    检测链表环:如果链表有环,快指针会绕圈追上慢指针,就像两个人在环形跑道上跑步总会相遇。 

    找链表中点:快指针到终点时,慢指针刚好在中点,类似“中间截断”。 

例子: 

  # 检测链表是否有环

  def has_cycle(head):

      slow = fast = head

      while fast and fast.next:

          slow = slow.next      # 乌龟走一步

          fast = fast.next.next # 兔子走两步

          if slow == fast:      # 相遇说明有环

              return True

      return False

  ```

2. 对撞指针(左右夹击) 

原理: 

  两个指针从两端向中间移动,像两把夹子逐渐合拢。常用于有序数组问题。 

应用: 

  两数之和:在有序数组中找两个数的和等于目标值,左右指针根据当前和调整位置。 

  反转字符串:左右指针交换字符,直到中间汇合。 

例子: 

  # 有序数组找两数之和

  def two_sum(nums, target):

      left, right = 0, len(nums)-1

      while left < right:

          s = nums[left] + nums[right]

          if s == target:

              return [left, right]

          elif s < target:  # 和太小,左指针右移

              left += 1

          else:             # 和太大,右指针左移

              right -= 1

  ```

3. 分离指针(分工合作)

原理: 

  两个指针分别操作不同的数据结构,比如一个遍历数组A,另一个遍历数组B。 

应用: 

  合并有序数组:两个指针分别扫描两个数组,按顺序合并。 

  数组去重:一个指针标记非重复位置,另一个扫描剩余元素。 

三、为什么用双指针?

1. 减少时间复杂度:将暴力解法的O(n²)优化为O(n),比如对撞指针避免嵌套循环。 

2. 节省空间:无需额外存储结构,直接在原数据上操作。 

3. 解决特定问题:如链表环、子数组求和、动态窗口等场景。

总结: 

指针是操作内存的“导航”,而双指针通过两人协作(快慢、对撞、分离)实现高效解题,就像快递员精准投递或团队分工合作清理仓库,既快又省力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星の迹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值