(四)双指针滑动算法
一、基本概念
双指针滑动算法通常用于求解连续的序列和的问题。
二、窗口设计与移动技巧
- 起点:设置两个起点left和right构成索引闭区间 [left, right],最初长度取决于题目要求,一般要求为1
- 限制条件:left<right,以符合索引闭区间的要求
- 区间索引移动要求:只能右移不能左移,基于此条理论,有三种移动方式:
(1)符合序列和要求:left右移
(2)小于序列和:right右移扩大窗口
(3)大于序列和:left右移缩小窗口
三、问题分析
下面以序列和问题进行分析和说明,原题表述如下:
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,获取所有和为S的连续正数序列。
算法选型:
由于需要保证数据的连续性,因而最适合的是双指针滑动法
采用上述设计技巧的算法逻辑:
import java.util.ArrayList; /** 思路:由于是连续数据,因而最好的方式是采用双指针,假设两个指针为start,end,则: (1)f(start,end) < s end++ (2)f(start,end) == s start++ (3)f(start,end) > s start++; 限制条件:start<end **/ public class Solution { public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) { ArrayList<ArrayList<Integer>> array = new ArrayList<ArrayList<Integer>>(); ArrayList<Integer> path = new ArrayList<Integer>(); // 至少包括两个数决定指针长度初始值为1 int start=1,end=2; while(start<end){ int data = f(start,end); if(data==sum){ path.clear(); for(int i=start;i<=end;i++){ path.add(i); } array.add(new ArrayList<Integer>(path)); start++; } if(data<sum){ end++; } if(data>sum){ start++; } } return array; } public int f(int start, int end){ int sum = 0; for(int i=start;i<=end;i++){ sum = sum + i; } return sum; } }
有疑问欢迎留言