1221. 四平方和 Java题解 (暴力,哈希,二分)【第七届蓝桥杯省赛C++A/B组,第七届蓝桥杯省赛JAVAB/C组】

35 篇文章 2 订阅
5 篇文章 0 订阅

目录

解题思路:

Java代码: (暴力)

Java代码: (哈希)

Java代码: (二分)


 

输入样例:

5

输出样例:

0 0 1 2

解题思路:

  • 暴力:三层for直接遍历,通过判断第四个数是否存在来找合适解。时间复杂度为 O(n)=n^3.
  • 哈希:对前两个数遍历两层for,第三个数和第四个数的乘积保存到哈希表中,在两层for遍历时,通过检验cd乘积是否存在来找合适解。理论上时间复杂度为 O(n)=n^2.
  • 二分:同样对前两个数两层for遍历,对剩下的两个数的乘积以及对应的c和d直接以对象的形式存入list中,再将list中的对象有序排列,当两层for遍历时,在list中通过二分查找第一次出现的cd乘积。时间复杂度为 O(n)=n^2·logn.

Java代码: (暴力)

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int n = scan.nextInt();
		scan.close();
		
		for(int a = 0; a * a <= n; a++) {
			for(int b = a; b *b + a *a <= n; b++) {
				for(int c = b; c * c + b * b + a * a <= n; c++) {
					int d = n - a * a - b * b - c * c;
					int t = (int)Math.sqrt(d);
					if(t * t == d) {//检验t是否是整数
						System.out.printf("%d %d %d %d", a, b, c, t);
						System.exit(0);
					}
				}
			}
		}
	}
}

Java代码: (哈希)

import java.util.*;

public class Main {
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int n = scan.nextInt();
		scan.close();
		
		Map<Integer, Pair1221> map = new HashMap<>();//哈希打表
		for(int c = 0; c * c <= n; c++) {
			for(int d = c; c * c + d * d <= n; d++) {
				int cd = c * c + d * d;
				Pair1221 value = map.get(cd);
				if(value == null) {//只存储第一次的情况,保证字典序最小
					map.put(cd, new Pair1221(c, d));
				}
			}
		}
		
		for(int a = 0; a * a <= n; a++) {
			for(int b = a; b * b + a * a <= n; b++) {
				int cd = n - a * a - b * b;
				if(map.get(cd) != null) {
					System.out.printf("%d %d %d %d", a, b, map.get(cd).x, map.get(cd).y);
					System.exit(0);
				}
			}
		}
	}
}
class Pair1221{//存放cd成绩所相应的c和d
	int x;
	int y;
	
	public Pair1221(int x, int y) {
		this.x = x;
		this.y = y;
	}
}

Java代码: (二分)

import java.util.*;

public class Main {
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int n = scan.nextInt();
		scan.close();
		List<Mul> list = new ArrayList<>();//打表
		for(int c = 0; c * c <= n; c++) {
			for(int d = c; d * d + c * c <= n; d++) {
				list.add(new Mul(c * c + d * d, c, d));
			}
		}
		Collections.sort(list);
		
		for(int a = 0; a * a <= n; a++) {
			for(int b = a; b * b + a * a <= n; b++) {
				int cd = n - a * a - b * b;
				
				int l = 0; 
				int r = list.size() - 1;
				while(l < r) {//二分查找
					int mid = l + r >> 1;
					if(list.get(mid).mul >= cd) r = mid;//找“最左面”的cd ,x<=arr[mid]
					else l = mid + 1;
				}
				if(list.get(l).mul == cd) {
					System.out.printf("%d %d %d %d", a, b, list.get(l).c, list.get(l).d);
					System.exit(0);
				}
			}
		}
	}
}
class Mul implements Comparable<Mul>{
	int mul;
	int c;
	int d;

	public Mul(int mul, int c, int d) {
		this.mul = mul;
		this.c = c;
		this.d = d;
	}

	@Override
	public int compareTo(Mul o) {//在乘积有序的前提下将cd字典序化
		if(this.mul != o.mul) {
			return this.mul - o.mul;
		}else if(this.c != o.c) {
			return this.c - o.c;
		}else {
			return this.d - o.d;
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值