Free Talk
之前刷题的时候,经常遇到双指针问题,打算写一篇专题,系统刷一下,总结一下常用的解题方法。
Finished Problem
颜色分类
75. 颜色分类
双指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class Solution { public void sortColors (int [] nums) { int left = 0 ; int right = nums.length - 1 ; for (int i = 0 ; i < nums.length ; i ++ ){ if (nums[i] < 1 ){ left ++; } if (nums[i] > 1 ){ right --; } } for (int i = 0 ; i < nums.length ; i ++ ){ if (i < left){ nums[i] = 0 ; }else if (i > right){ nums[i] = 2 ; }else { nums[i] = 1 ; } } } }
执行结果
环形链表
141. 环形链表
集合存放
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class Solution { public boolean hasCycle (ListNode head) { Set<ListNode> set = new HashSet<ListNode>(); while (head != null ){ if (!set.add(head)){ return true ; } head = head.next; } return false ; } }
执行结果
快慢指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public class Solution { public boolean hasCycle (ListNode head) { if (head == null || head.next == null ){ return false ; } ListNode slow = head.next; ListNode fast = head.next.next; while (slow != fast){ if (fast == null || fast.next == null ){ return false ; } slow = slow.next; fast = fast.next.next; } return true ; } }
执行结果
环形链表 II
142. 环形链表 II
快慢指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 public class Solution { public ListNode detectCycle (ListNode head) { if (head == null || head.next == null ){ return null ; } ListNode fast = head; ListNode slow = head; while (true ){ if (fast == null || fast.next == null ) return null ; fast = fast.next.next; slow = slow.next; if (fast == slow) break ; } ListNode pre = head; while (pre != slow){ pre = pre.next; slow = slow.next; } return pre; } }
执行结果
反转链表
206. 反转链表
双指针迭代
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution { public ListNode reverseList (ListNode head) { ListNode pre = null ; ListNode cur = head; while (cur != null ){ ListNode tmp = cur.next; cur.next = pre; pre = cur; cur = tmp; } return pre; } }
执行截图
回文链表
234. 回文链表
链表反转 + 快慢指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 class Solution { public boolean isPalindrome (ListNode head) { if (head == null || head.next == null ) return true ; ListNode mid = generateMiddle(head); ListNode rvs = reverseList(mid); while (rvs != null ){ if ( rvs.val != head.val ){ return false ; } rvs = rvs.next; head = head.next; } return true ; } public ListNode generateMiddle (ListNode head) { ListNode slow = head; ListNode fast = head; while (fast != null && fast.next != null ){ slow = slow.next; fast = fast.next.next; } return slow; } public ListNode reverseList (ListNode head) { ListNode pre = null ; ListNode cur = head; while (cur != null ){ ListNode tmp = cur.next; cur.next = pre; pre = cur; cur = tmp; } return pre; } }
执行截图
移动零
283. 移动零
指针记录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Solution { public void moveZeroes (int [] nums) { int j = 0 ; for (int i = 0 ; i < nums.length ; i ++ ){ if (nums[i] != 0 ){ nums[j ++] = nums[i]; } } for (int i = j ; i < nums.length ; i ++ ){ nums[i] = 0 ; } } }
执行结果
一次遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution { public void moveZeroes (int [] nums) { int j = 0 ; for (int i = 0 ; i < nums.length ; i ++ ){ if (nums[i] != 0 ){ int tmp = nums[i]; nums[i] = nums[j]; nums[j ++] = tmp; } } } }
执行结果
寻找重复数
287. 寻找重复数
二分法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class Solution { public int findDuplicate (int [] nums) { int left = 0 ; int right = nums.length - 1 ; while (left < right){ int mid = (left + right) >>> 1 ; int count = 0 ; for (int num: nums){ if (num <= mid){ count ++; } } if (count > mid){ right = mid; }else { left = mid + 1 ; } } return left; } }
执行结果
完结撒花