当前位置: 首页 > news >正文

【算法】day6 双指针补充

1、接雨水(相撞,单调性)hot

题目:42. 接雨水 - 力扣(LeetCode)

分析

时间复杂度:O(n),只遍历了一次柱子。

空间复杂度:O(1),只用了几个额外变量。

代码

class Solution {public int trap(int[] height) {int left = 0, right = height.length - 1; // 最左、最右柱子int leftMax = 0, rightMax = 0; // 最左柱左边无柱,最右柱右边无柱int sum = 0;while(left <= right) {// leftMax 为左柱的两边最高柱的较小柱if (leftMax <= rightMax) {int tmp = leftMax - height[left];if (tmp >= 0) sum += tmp;// left 位置积水已算完,更新 leftMax,遍历下一个柱子leftMax = Math.max(leftMax, height[left++]);} else { // rightMax 为右柱的两边最高柱的较小柱int tmp = rightMax - height[right];if (tmp >= 0) sum += tmp;// right 位置积水已算完,更新 rightMax,遍历下一个柱子rightMax = Math.max(rightMax, height[right--]);}}return sum;}
}

 2、轮转数组 hot

题目:189. 轮转数组 - 力扣(LeetCode)

分析

① 朴素方法:遍历数组,每次将 i 处数字放到新数组 (i+k)%n 的位置,使用新数组是避免移动的数字覆盖该位置原数字。

时间:O(n)

空间:O(n)

② 双指针:实现数组翻转。

m = k % n,对于长度 n 为 3 的数组,轮转 k=10 次只需轮转 10 % 3 = 1 次。

第一次翻转,[0, n-1]:把 5、6、7 放到前面,1、2、3、4 放到后面。

第二次翻转,[0, m - 1]:把 5、6、7 恢复原来正序。

第三次翻转,[m, n-1]:把 1、2、3、4 恢复原来正序。

时间:O(2n)=O(n)

空间:O(1)

代码

class Solution {// 数组翻转private void reverse(int[] nums, int start, int end) {int tmp;while(start < end) {if (nums[start] != nums[end]) {tmp = nums[start];nums[start] = nums[end];nums[end] = tmp;}start++;end--;}}// 数组轮转public void rotate(int[] nums, int k) {int n = nums.length;int m = k % n;if (k == 0) return;reverse(nums, 0, n-1);reverse(nums, 0, m - 1);reverse(nums, m, n-1);}
}

3、相交链表 hot

题目160. 相交链表 - 力扣(LeetCode)

分析:可以让双指针相遇,相遇的地方就是相交结点;如果没有相遇,则没有相交节点。那么两指针需要走同样的步数,那么较长链表需要提前走 |链A长 - 链B长| 步。

代码

public class Solution {// 求链长private int size(ListNode head) {ListNode cur = head;int cnt = 0;while(cur != null) {cnt++;cur = cur.next;}return cnt;}public ListNode getIntersectionNode(ListNode headA, ListNode headB) {// 求两条链的长度int sizeA = size(headA);int sizeB = size(headB);// 求链长差int len = Math.abs(sizeA - sizeB);// 让长的先走 len 步ListNode headMax = sizeA >= sizeB ? headA : headB;ListNode headMin = sizeA < sizeB ? headA : headB;while(len-- != 0) headMax = headMax.next;// 再同时走,相等的地方就是相交结点;若没有交点,A、B 都会在 null 处停下while(headMax != headMin) {headMax = headMax.next;headMin = headMin.next;}return headMax;}
}

4、环形链表(快慢指针测环) hot

题目:141. 环形链表 - 力扣(LeetCode)

分析:慢指针每次走1步,快指针每次走2步。如果有环,它们总会相遇;如果没有环,快指针会先到链尾(偶数个节点:fast.next == null 或 奇数个节点:fast == null)。

代码

public class Solution {public boolean hasCycle(ListNode head) {if (head == null) return false;// 初始化快慢指针ListNode slow = head; // 每次走一步ListNode fast = head.next; // 每次走两步// 有环:slow 与 fast 相遇// 无环:fast == null 或 fast.next == nullwhile(fast != null && fast.next != null) {if(slow == fast) {return true;}slow = slow.next;fast = fast.next.next;}return false;}
}

5、环形链表Ⅱ(快慢指针测环)hot

题目:142. 环形链表 II - 力扣(LeetCode)

分析:只要求出 head 到入口节点的长度 x,就能求到入口节点。

slow 与 fast 第一次相遇:

slow 走了:x + (y-n)

fast 走了:x + (y-n) + ay

slow 与 fast 的关系:2[x + (y-n)] = x + (y-n) + ay

得到: x = (a-1)y + n

故从 head 走 x 步到达入口;从相遇点走 n + (a-1)y 步也到达入口。

结论:两节点从 head、slow 和 fast 相遇点同时走,最终会在入口处相遇。

代码

public class Solution {// 求相遇点private ListNode getMeetNode(ListNode head) {if (head == null) return false;// 初始化快慢指针ListNode slow = head;ListNode fast = head.next;while(fast != null && fast.next != null) {if(slow == fast) {return slow;}slow = slow.next;fast = fast.next.next;}return null;}// 求入口点public ListNode detectCycle(ListNode head) {// 获得 slow 与 fast 的相遇结点ListNode meetNode = getMeetNode(head);// 链表无环,返回 nullif(meetNode == null) {return null;}// 分别从头指针,相遇结点开始走,两指针相遇处就是入口while(head != meetNode) {head = head.next;meetNode = meetNode.next;}return head;}
}

6、删除链表的倒数第 N 个节点 hot

题目:19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)

分析

朴素方法:因为是单链表,不能从链尾往回数,所以要先遍历链表计算链长 size,再从头走 size - n + 1 步删除节点,所以时间复杂度是 O(size^2)。

双指针:右指针先多走 n-1 步,然后同时走。最终右指针走到链尾,左指针停下的地方就是倒数第 n 个结点。但是删除的是左指针指向的节点,所以还要记录左指针的前一个节点。

时间复杂度:O(size)

空间复杂度:O(1)

代码

class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {// 初始左右指针,右指针先多走 n-1 步ListNode leftNode = head;ListNode rightNode = head;for (int i = 0; i < n-1; i++) rightNode = rightNode.next;// 然后同时走,直到右指针走到链尾,同时要记录左指针的前一个节点ListNode previous = null;while(rightNode.next != null) {previous = leftNode;leftNode = leftNode.next;rightNode = rightNode.next;}// 删除倒数第 n 个节点if(leftNode == head) head = leftNode.next;else previous.next = leftNode.next;leftNode = null;return head;}
}
http://www.dtcms.com/a/492703.html

相关文章:

  • 手机网站设计理念建筑工程公司有哪些
  • 网站建设中轩网怎么样怎么制作网站?
  • TSMaster软件的使用
  • 如何做网站源码备份上海网站建设选缘魁
  • 可以做夫妻的游戏视频网站php 多语言网站建设源码
  • Java---包装类
  • 深圳企业网站建设公司义乌做网站公司
  • 带做网站win10怎么删除2345网址导航
  • 企业网站开发框架如何制作简单的网站
  • 简述网站的制作步骤网站建设经费申请
  • c 网站开发数据库连接产品关键词大全
  • protected 和默认,都能被子类访问吗
  • 鲜花网站建设项目策划书公司做网站的费用属于什么费用
  • 做微课的网站有哪些建立什么船籍港
  • 网站分析与优化皮具网站设计
  • 教育培训网站建设方案模板蓬莱建设管理局网站
  • 网站表单点击切换判断网站的好坏
  • 强化学习:Gym环境,自定义奖励函数设计?
  • 做电影网站需要服务器吗婚礼纪网站怎么做请帖
  • 做网站用模板便宜做网站怎么样
  • 网站负责人不是法人做繁体书的网站
  • 建设专业网站的价格企业门户网站解决方案
  • 静态网站模板 大气wordpress更新以后进不去
  • Qtday2
  • 佛山新网站建设特色公司网站建设介绍
  • 监控进程创建
  • 外贸箱包网站模板wordpress内存占用
  • 网站功能是什么重庆室内设计
  • 做特产的网站个人备案网站做盈利合法吗
  • 高明网站设计网站建设通知