思路 双指针,顾名思义,是指在遍历某个数组时用两个指针指向不同元素,协同达成某些目的。 也可扩展为多数组多指针。
 
Two Sum II 问题描述 在一个增序的整数数组里找到两个数,使它们的和为给定值。
已知有且只有一对解解题思路 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 func  twoSum (numbers []int , target int )  []int   {	left := 0  	right := len (numbers) - 1  	for  left < right { 		leftNum := numbers[left] 		rightNum := numbers[right] 		total := leftNum + rightNum 		if  total == target { 			break  		} 		if  total > target { 			right-- 			continue  		} 		if  total < target { 			left++ 			continue  		} 	} 	result := [2 ]int {left + 1 , right + 1 } 	return  result[0 :] } 
 
Merge Sorted Array 问题描述 给定两个排序整数数组nums1和nums2,合并nums2成nums1为一个排序后的数组。
元件的数量初始化中nums1和nums2是m和n分别。您可以假定nums1大小等于m + n,使其具有足够的空间来容纳
中的其他元素nums2。解题思路 思路1 因为nums1是有序的,
所以可以使用插入排序将nums2中的数据依次插入到nums1中1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 func  merge (nums1 []int , m int , nums2 []int , n int )   {	if  m == 0  { 		copy (nums1, nums2) 		return  	} 	pointer1 := m - 1  	pointer2 := 0  	for  ; pointer1 < m+n && pointer2 < n; pointer1++ { 		if  nums2[pointer2] >= nums1[pointer1] { 			nums1[pointer1+1 ] = nums2[pointer2] 		} else  if  nums2[pointer2] < nums1[pointer1] { 			count := pointer1 			for  ; count >= 0  && nums2[pointer2] < nums1[count]; count-- { 				nums1[count+1 ] = nums1[count] 			} 			nums1[count+1 ] = nums2[pointer2] 		} 		pointer2++ 	} } 
 
思路2 但是使用插入排序就浪费了nums2有序的条件,所以这里更好的思路是从两个数组最大的数开始比较,将其中更
大的插入nums1的尾部。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 func  merge (nums1 []int , m int , nums2 []int , n int )   {	 	last := m + n - 1  	 	p1 := m - 1  	 	p2 := n - 1  	for  p1 >= 0  && p2 >= 0  { 	     		if  nums1[p1] >= nums2[p2] { 			nums1[last] = nums1[p1] 			p1-- 		} else  { 			nums1[last] = nums2[p2] 			p2-- 		} 		 		last-- 	} 	 	for  ; p2 >= 0 ; p2-- { 		nums1[last] = nums2[p2] 		last-- 	} } 
 
Linked List Cycle II 问题描述 给定一个链表,返回循环开始的节点。如果没有循环,则返回null。
如果列表中有某些节点可以通过连续跟随next 指针再次到达,则链接列表中会有一个循环 。
在内部,pos 用于表示尾部next 指针连接到的节点的索引 。解题思路 使用快慢指针(Floyd判圈法)就很容易的解决这个问题。
首先定义fast,slow两个指针,一个每次遍历两个节点,一个每次遍历一个节点。
如果,fast遍历到链表尽头,则表示没有循环;
反之,当fast,slow节点第一次相遇时,将fast节点复位到头节点,然后调整
fast节点每次也只遍历一个节点,这时,当fast与slow第二次相遇时的节点就是
循环的起始节点。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 type  ListNode struct  {	Val  int  	Next *ListNode } func  detectCycle (head *ListNode)  *ListNode   {	if  head == nil  || head.Next == nil  { 		return  nil  	} 	fast := head.Next.Next 	slow := head.Next 	for  fast != slow { 		if  fast == nil  || fast.Next == nil  { 			return  nil  		} 		fast = fast.Next.Next 		slow = slow.Next 	} 	fast = head 	for  fast != slow { 		fast = fast.Next 		slow = slow.Next 	} 	return  fast } 
 
Minimum Window Substring 问题描述 给定两个字符串 S 和T,求 S 中包含T 所有字符的最短连续子字符串的长度,同时要求时间
复杂度不得超过 O(n)。解题思路 使用滑动窗口,定义两个指针start,end。先移动end找到包含目标字符串的子字符串,然后移动将start
向end靠近,尝试找到最短的子字符串。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 func  minWindow (s string , t string )  string   {	tSize := len (t) 	sSize := len (s) 	 	 	 	checkArray := make (map [uint8 ]int , tSize) 	 	countArray := make (map [uint8 ]int , tSize) 	 	 	 	 	start, end, minS, totalCount, countNum := 0 , 0 , 0 , 0 , 0  	 	minLen := sSize + 1  	 	for  e := range  t { 		if  checkArray[t[e]] == 0  { 			totalCount++ 		} 		checkArray[t[e]]++ 	} 	 	for  ; end < sSize; end++ { 	     		if  checkArray[s[end]] > 0  { 			countArray[s[end]]++ 			if  countArray[s[end]] == checkArray[s[end]] { 				countNum++ 			} 		} 		 		for  ; totalCount == countNum; start++ { 			currentLen := end - start + 1  			if  minLen > currentLen { 				minS = start 				minLen = currentLen 			} 			if  checkArray[s[start]] > 0  { 				countArray[s[start]]-- 				if  countArray[s[start]] < checkArray[s[start]] { 					countNum-- 				} 			} 		} 	} 	if  minLen == sSize+1  { 		return  ""  	} 	return  s[minS : minS+minLen] } 
 
总结 双指针算法很显然,适用于对数组这类数据的操作问题。
但他的变化比较多,首先会有多指针多数组的情况,不同的问题,解决思路也大同小异,
例如上述判圈法和滑动窗口,虽然都是两个指针协作的思路,但具体实现却很不一样。
一方面需要把握其通过多个指针协同解决的主题思路,另一方面还是需要多多练习不同的
题目。