2021-05-05数组求和积最小for菜鸡


前言

一、题目

输出和为s的数组元素
Description
输入一个递增排序的数组和数字s
在数组中查找两个数,使得他们的和恰好为s。
如果有多对数字的和等于s,输出两个数的乘积最小的
Input
输入第一个数 n 表示数组长度
输入第二个数 s 表示两个数之和
其余数组中的数按空格分开输入
Output
输出满足条件的两个元素

二、解题思路

这道题如果暴力一点怎么做都好,但是如果想要又快又好,那就得花点心思。
注意一点,该数组是递增的。本题需要一个数学知识,两个数的差值越小,则两个数的乘积越大
证明如下:
假设固定两数的平均值 m,设 d 为两数与平均值的差,则 a = m + d, b = m - d
ab = (m + d)(m - d) = m^2 - d^2
可见 d 越小(即,两数离平均值越近,也就是两数差值越小),乘积越大

(不考虑数组中的数没有组合等于输入的数的情况)
所以为了让我们输出的两个数乘积越小,这两个数就越需要靠向两侧,而不是中间。所以应该从两侧开始搜索。
我们可以定义一个i变量指向数组头部,j变量指向数组尾部,如果最开始arry[i]+arry[j]>s(我们输入的数)那么说明这两个数的和偏大,需要j–,这个时候i不能++也不能–,因为–会使得arry越界,而++会使得arry[i]+arry[j]更大于s。当最开始的时候arry[i]+arry[j]<s时,需要i++,j不能++也不能–因为j++数组越界,j–会使得arry[i]+arry[j]更小于s。
一般情况下如果arry[i]+arry[j]>s那么会使得j–,那么下一次如果是arry[i]+arry[j]>s那么还是j–,若为arry[i]+arry[j]<s则应为i–,不会是j++因为这样就回到上一个状态了,避免绕圈,所以两个条件只需要做i++或j–。

代码如下:

#include<stdio.h>



int main() {
	int arry[100] = { 0 };
	int n = 0;
	int s = 0;
	scanf("%d %d", &n, &s);
	for (int i = 0; i < n; i++) {
		scanf("%d", &arry[i]);
	}
	int i = 0;
	int j = n - 1;
	while (i < j) {
		if (arry[i] + arry[j] > s) {
			j--;
		}
		else if (arry[i] + arry[j] < s) {
			i++;
		}
		else {
			printf("%d %d", arry[i], arry[j]);
			break;
		}
	}
		return 0;
}

总结

千万别老虎念经——假正经
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值