(四)双指针滑动算法

一、基本概念

 

   双指针滑动算法通常用于求解连续的序列和的问题。

 

二、窗口设计与移动技巧

 

  • 起点:设置两个起点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;
    }
}

 

posted @ 2020-05-19 21:22  FCity  阅读(309)  评论(0编辑  收藏  举报