尺取り法(英語名:Two Pointer Technique)

はじめに(Two Pointer Technique)

尺取り法(英語名:Two Pointer Technique)についての解説記事です.Atcoder ABC130Dの問題で,尺取り法を使わないとテストコードが時間内に終わりません.そこで,尺取り法について学んだので,その内容をシェアしたいと思います.尺取り法の学習には,こちらの英語Web記事を参考にしました.

尺取り法(Two Pointer Technique)とは

1つの配列内の要素同士を比較する際,配列内のある2個の要素を示す「2個のポインタ(Two Pointer)」を使って比較すること.ポインタを使うことで,「要素比較の2回ループ」を「2個のポインタを動かす1回ループ」にすることができ,計算量を減らすことができる.それでは,Atcoder ABC130Dを「2回ループを使用する方法」と「尺取り法」を使う方法で解きます.

例題1

Atcoder ABC130Dの問題 D - Enough Array | AtCoder Beginner Contest 130 | AtCoder

「2回ループを使用」

配列の要素2つをi,jで表現して,2回ループしています.

import java.util.*;

public class Main{
    public static void main(String[] arg){
        Scanner scan =new Scanner(System.in);
        int n=scan.nextInt();
        int k=scan.nextInt();
        int[] A=new int[n];

        for(int i=0;i<n;i++){
            A[i]=scan.nextInt();
        }

        long sum=0;
        long ans=0;

        for(int i=0;i<n;i++){
            loop:for(int j=i;j<n;j++){
                if(j==i) {
                    sum=A[j];
                }
                else{
                    sum=sum+A[j];
                }
                if(sum>=k) {
                    ans=ans+n-j;
                    break loop;
                }
            }
        }
        System.out.print(ans);
    }
}

「尺取り法」

条件を満足する最小の和を持つ部分配列の,左と右の要素をpoint1,2でそれぞれ表現しています.

import java.util.*;
import java.lang.*;
import java.io.*;

public class ABC130D_2{
    public static void main(String[] arg){
        Scanner scan =new Scanner(System.in);
        int n=scan.nextInt();
        long k=scan.nextLong();
        long[] A=new long[n];

        for(int i=0;i<n;i++){
            A[i]=scan.nextLong();
        }

        long sum=0;
        long ans=0;
        int point2=0;

        for(int point1=0;point1<n;point1++){
            while(sum<k){
                if(point2==n) break;
                else{
                    sum+=A[point2];
                    point2++;
                }
            }
            if(sum<k) break;
            ans+=n-point2+1;
            sum-=A[point1];
        }
        System.out.print(ans);
    }
}

おわりに

例題を追加していきたいと思います.