尺取法

同學推薦的一題,看了別人及講解,學到了一點新的東西------尺取法
例題如下:
Description

A sequence of N positive integers (10 < N < 100 000), each of them less than or equal 10000, and a positive integer S (S < 100 000 000) are given. Write a program to find the minimal length of the subsequence of consecutive elements of the sequence, the sum of which is greater than or equal to S.
Input

The first line is the number of test cases. For each test case the program has to read the numbers N and S, separated by an interval, from the first line. The numbers of the sequence are given in the second line of the test case, separated by intervals. The input will finish with the end of file.
Output

For each the case the program has to print the result on separate line of the output file.if no answer, print 0.
Sample Input
2
10 15
5 1 3 5 10 7 4 9 2 8
5 11
1 2 3 4 5
Sample Output
2
3
自己是真的菜,所有題目拿到的第一反應都是暴力求解,看完別人的纔想到有尺取法這麼有效的東西。
尺取法
就是像尺一樣可以伸長與縮小。
步驟1主要是先初始化左右端點,怎麼初始化呢?先是找到符合條件的端點,即從第一個端點開始往後延伸,直到出現符合條件的端點
步驟2就是開始縮減區間的長度,這裏重要的判斷標準就是,如果條件成立,那就將左端點向右延伸,左端點不動,但是一旦出現條件不成立的情況,就應該將右端點向左延伸,直到條件滿足位置,重複此循環直到整個數組都經歷過判斷後即可,時間複雜度從O(n*n)降到了O(n),非常方便。

import java.util.Scanner;

public class num3061第二版 {
	public static void figure(int []num,int n)
	{
		int sum=0;
		for(int i=0;i<num.length;i++)
			sum+=num[i];
		if(sum<n)
			System.out.println(0);
		else 
		{
			int s1=0,s2=0,res=num.length,sum1=0;
			for(;;)
			{
				while(s1<num.length&&sum1<n)//這裏進行初始化左右端點
					sum1+=num[s1++];
				if(sum1<n)
					break;
				res=Math.min(res, s1-s2);//每次結算最小的區間長度
				sum1-=num[s2++];
			}
			System.out.println(res);
		}
	}
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		for(int i=0;i<n;i++)
		{
			int m1=sc.nextInt();
			int m2=sc.nextInt();
			int []num=new int [m1];
			for(int j=0;j<m1;j++)
				num[j]=sc.nextInt();
			figure(num, m2);
		}
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章