CCF 模拟题 202006-2 稀疏向量 Java 100分

CCF练习 202006-2 稀疏向量 二分查找yyds

题目心得

学过线性代数的同学应该对稀疏矩阵并不陌生,这道题的思路很简单:读入a数组,如果数组b和数组a中存在同样不为零的维度,那么就把这个维度上的数值相乘,最后相加。

我们一步步分解来看:

  1. 读入数组a
int[][] ara = new int[a][2];
		for(int i=0;i<a;i++){
			ara[i][0] = sc.nextInt();
			ara[i][1] = sc.nextInt();
		}
  1. 按行读入数组b,而不进行储存,因为我们的目标是得到内积,所以数组储存下来没有意义。只需要对数组b中有意义的元素进行计算,有意义的规则就是:两个数组的这个维度都不为零。这个时候就需要我们在数组a中查找是否存在这样的维度。
    由于维度的序列是有序的,并且涉及到了大数量下的查找问题,这个时候就可以很自然地想到使用二分查找。这也是这道题拿100分的关键。
    至于二分查找的算法,我在这里给出一种写法。这个写法是对于排序的基础上应用的。
//读取数组b当中的非零值和下标
		for(int i=0;i<b;i++){
			int[] tmp = new int[]{sc.nextInt(), sc.nextInt()};
			//如果存在相同的下标,则说明在这个维度上相乘结果不为零
			//现在的目标是找到数组a中是否含有该下标
			//由于下标的序列是有序的,所以可以使用二分查找
			
			int l = 0;
			int r = a-1;
			while(l<=r){
				if (tmp[0]<ara[l][0] || tmp[0]>ara[r][0]) {
					break;
		        }
				int m = (l+r)/2;
				if(tmp[0]<ara[m][0]){
					r = m-1;
				}else if(tmp[0]>ara[m][0]){
					l = m+1;
				}else{
					res += tmp[1]*ara[m][1];
					break;
				}
			}
		}
  1. 找到可以同一维度上的非零元素,累加乘积。对于累计相加的问题,我们一般都是先声明一个变量存储,如rus,然后找到可以进行累计相加的“规则”,然后使用rus += 某些算式。

  2. 最后,还有一些小细节:

  • 不需要考虑维度从0还是从1开始:因为我们把维度考虑成数值,而不是标号或者索引。
  • 使用long储存最后的内积结果:遇到数据值比较大的题目都留意一下这个小细节,虽然有时候可能真的没有用到long,但是以防万一还是用long代替int吧,反正只需要更改一个变量。

完整代码

由于本人学术不精,粘出代码仅供大家参考,欢迎大家参与讨论和批评指正。

import java.util.Scanner;
public class Main {
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int a = sc.nextInt();
		int b = sc.nextInt();
		long res = 0;//记录内积的结果
		//存储数组a当中的非零值和下标
		int[][] ara = new int[a][2];
		for(int i=0;i<a;i++){
			ara[i][0] = sc.nextInt();
			ara[i][1] = sc.nextInt();
		}
		//读取数组b当中的非零值和下标
		for(int i=0;i<b;i++){
			int[] tmp = new int[]{sc.nextInt(), sc.nextInt()};
			//如果存在相同的下标,则说明在这个维度上相乘结果不为零
			//现在的目标是找到数组a中是否含有该下标
			//由于下标的序列是有序的,所以可以使用二分查找
			
			int l = 0;
			int r = a-1;
			while(l<=r){
				if (tmp[0]<ara[l][0] || tmp[0]>ara[r][0]) {
					break;
		        }
				int m = (l+r)/2;
				if(tmp[0]<ara[m][0]){
					r = m-1;
				}else if(tmp[0]>ara[m][0]){
					l = m+1;
				}else{
					res += tmp[1]*ara[m][1];
					break;
				}
			}
		}
		System.out.println(res);
		sc.close();
	}
}

提交结果:
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值