【二分搜索】HDU-2141 Can you find it?

在这里插入图片描述

注解

1、暴力解法:三重循环,TLE。
2、两重循环,第三个数采用二分搜索:仍然TLE。
3、把前2个数的和存在一个数组里,排序,然后遍历第三个数,对前2个数进行二分搜索:AC。
4、二分搜索可以采用STL中的版本,也可以手写。语言可以用C++,也可以用Java。都可以顺利AC。若采用Java,要采用快速输入节省时间。

代码

1、C++ STL二分搜索版本:

#include <iostream>
#include <algorithm>

using namespace std;

int main() {

	int L, N, M;
	int cas = 1;
	while(scanf("%d %d %d", &L, &N, &M)>0) {
		printf("Case %d:\n", cas++);
		int A[L];
		int B[N];
		int C[M];
		for(int i=0; i<L; i++) {
			scanf("%d", &A[i]);
		}
		for(int i=0; i<N; i++) {
			scanf("%d", &B[i]);
		}
		for(int i=0; i<M; i++) {
			scanf("%d", &C[i]);
		}
		
		//对前2个数遍历,求和后放在一个数组中,排序(方便后面进行二分搜索)。
		int ABsum[L*N];
		int pos = 0;
		for(int i=0; i<L; i++) {
			for(int j=0; j<N; j++) {
				ABsum[pos++] = A[i]+B[j];
			}
		}
		sort(ABsum, ABsum+L*N);

		int q;
		scanf("%d", &q);
		for(int i=0; i<q; i++) {
			bool flag = false;
			int num;
			scanf("%d", &num);
			//对C遍历,在ABsum中查找是否存在num-C[j]
			for(int j=0; j<M; j++) {
				if(binary_search(ABsum, ABsum+L*N, num-C[j])) {
					flag = true;
					printf("YES\n");
					break;
				}
			}
			if(!flag) {
				printf("NO\n");
			}
		}
	}

	return 0;
}

2、C++,手写二分搜索版本:

#include <iostream>
#include <algorithm>

using namespace std;

//循环写法,只需要传数组名、数组长度、要查找的数字。
//如果采用递归写法,还要加上start,end坐标。
int binarySearch(int a[], int len, int num) {
	int left = 0;
	int right = len-1;
    //这个地方一定是小于等于
    //下面的left,right,分别是mid+1和mid-1
	while(left<=right) {
		int mid = (left+right)/2;
		if(a[mid]==num) {
			return mid;
		} else if(a[mid]<num) {
			left = mid+1;
		} else {
			right = mid-1;
		}
	}
	return -1;
}

int main() {

	int L, N, M;
	int cas = 1;
	while(scanf("%d %d %d", &L, &N, &M)>0) {
		printf("Case %d:\n", cas++);
		int A[L];
		int B[N];
		int C[M];
		for(int i=0; i<L; i++) {
			scanf("%d", &A[i]);
		}
		for(int i=0; i<N; i++) {
			scanf("%d", &B[i]);
		}
		for(int i=0; i<M; i++) {
			scanf("%d", &C[i]);
		}

		int ABsum[L*N];
		int pos = 0;
		for(int i=0; i<L; i++) {
			for(int j=0; j<N; j++) {
				ABsum[pos++] = A[i]+B[j];
			}
		}
		sort(ABsum, ABsum+L*N);

		int q;
		scanf("%d", &q);
		for(int i=0; i<q; i++) {
			bool flag = false;
			int num;
			scanf("%d", &num);
			for(int j=0; j<M; j++) {
				int index = binarySearch(ABsum, L*N, num-C[j]);
				if(index>=0) {
					flag = true;
					printf("YES\n");
					break;
				}

			}
			if(!flag) {
				printf("NO\n");
			}
		}
	}

	return 0;
}

3、Java,手写二分搜索,快速输入:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.Arrays;

public class Main {

	public static int binarySearch(int[] a, int num) {
		int left = 0;
		int right = a.length - 1;

		while (left <= right) {
			int mid = (left + right) / 2;
			if (a[mid] == num) {
				return mid;
			} else if (a[mid] < num) {
				left = mid + 1;
			} else {
				right = mid - 1;
			}
		}
		return -1;
	}

	public static void main(String[] args) throws IOException {

		StreamTokenizer sc = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));

		int count = 1;
		//读到输入结束
		while (sc.nextToken() != sc.TT_EOF) {

			System.out.println("Case " + count + ":");
			count++;

			int L = (int) sc.nval;
			sc.nextToken();
			int N = (int) sc.nval;
			sc.nextToken();
			int M = (int) sc.nval;

			int[] A = new int[L];
			int[] B = new int[N];
			int[] C = new int[M];

			for (int i = 0; i < L; i++) {
				sc.nextToken();
				A[i] = (int) sc.nval;
			}

			for (int i = 0; i < N; i++) {
				sc.nextToken();
				B[i] = (int) sc.nval;
			}

			for (int i = 0; i < M; i++) {
				sc.nextToken();
				C[i] = (int) sc.nval;
			}

			int[] ABsum = new int[L * N];
			int tmp = 0;
			for (int i = 0; i < L; i++) {
				for (int j = 0; j < N; j++) {
					ABsum[tmp++] = A[i] + B[j];
				}
			}
			Arrays.sort(ABsum);

			sc.nextToken();
			int S = (int) sc.nval;
			int[] q = new int[S];
			for (int i = 0; i < S; i++) {
				sc.nextToken();
				q[i] = (int) sc.nval;
			}

			for (int query = 0; query < S; query++) {
				boolean flag = false;
				for (int i = 0; i < M; i++) {
					if (binarySearch(ABsum, q[query] - C[i]) >= 0) {
						flag = true;
						System.out.println("YES");
						break;
					}
				}
				if (!flag) {
					System.out.println("NO");
				}
			}
		}
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值