剑指Offer-和为S的两个数字

题目描述

输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。

输出描述: 对应每个测试案例,输出两个数,小的先输出。

思路

思路一:

数列满足递增,设首尾两个变量left和right

若array[left] + array[right] == sum,则这一对就是结果(两个数的和一定,它们的差越小,乘积越大)

若array[left] + array[right] > sum,array[right]肯定不是答案之一,right--

若array[left] + array[right] < sum,array[left]肯定不是答案之一,left++

时间复杂度 O(n)

思路二:

使用HashMap存储数组元素值和下标,然后开始遍历数组找到和为sum的两个元素,从左到右找到的第一对和为sum的就是最小的一对。

注:证明两个数的和一定,它们的差越小,乘积越大。

设两个数a和b的和为m,则有:$ab=a(m-a)$, 配方成$m^2/4-(a-m/2)^2$. 可见,a赿接近m/2,乘积ab就越大,也就是a、b的差越小,乘积越大。

代码实现

package Array;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * 和为S的两个数字
 * 输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
 * 对应每个测试案例,输出两个数,小的先输出。
 */
public class Solution34 {
    public static void main(String[] args) {
        Solution34 solution34 = new Solution34();
        int[] array = {1, 2, 3, 4, 5, 6};
        int sum = 5;
        System.out.println(solution34.FindNumbersWithSum_2(array, sum));

    }

    /**
     * 两头夹逼
     *
     * @param array
     * @param sum
     * @return
     */
    public ArrayList<Integer> FindNumbersWithSum(int[] array, int sum) {
        ArrayList<Integer> result = new ArrayList<>();
        int left = 0;
        int right = array.length - 1;
        while (left < right) {
            if (array[left] + array[right] == sum) {
                result.add(array[left]);
                result.add(array[right]);
                break;
            } else if (array[left] + array[right] > sum) {
                right--;
            } else {
                left++;
            }
        }
        return result;
    }

    /**
     * 用HashMap存放元素和下标,然后开始遍历数组找到和为sum的两个元素,从左到右找到的第一对和为sum的就是最小的一对。
     *
     * @param array
     * @param sum
     * @return
     */
    public ArrayList<Integer> FindNumbersWithSum_2(int[] array, int sum) {
        HashMap<Integer, Integer> map = new HashMap<>();
        ArrayList<Integer> result = new ArrayList<>();
        int len = array.length;
        for (int i = 0; i < len; i++) {
            map.put(array[i], i);
        }
        for (int i = 0; i < len; i++) {
            int sub = sum - array[i];
            if (map.containsKey(sub)) {
                result.add(array[i]);
                result.add(sub);
                break;
            }
        }
        return result;
    }
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏用户2442861的专栏

Java中如何遍历Map对象的4种方法

既然java中的所有map都实现了Map接口,以下方法适用于任何map实现(HashMap, TreeMap, LinkedHashMap, Hashtabl...

1061
来自专栏Android开发指南

12:集合map、工具类

3668
来自专栏Java大联盟

Java面试手册:集合框架

2453
来自专栏LinkedBear的个人空间

唠唠SE的集合-01——Collection接口

当集合中存储的对象类型不同时,那么会导致程序在运行的时候的转型异常,所以jdk1.5加入了泛型机制。

682
来自专栏Android群英传

深入Java源码解析容器类List、Set、Map

2153
来自专栏电光石火

Java遍历Map对象的四种方式

关于java中遍历map具体哪四种方式,请看下文详解吧。 方式一 这是最常见的并且在大多数情况下也是最可取的遍历方式。在键值都需要时使用。 Map<I...

42810
来自专栏Java后端技术栈

初探Java源码之ArrayList

在我们的日常开发中,集合类是我们基本上每个人都会用经常用到的东西,用着用着,突然有一天我心生好奇,那么java集合类的这些源码是什么呢?那么我打算接下来一个...

811
来自专栏Kevin-ZhangCG

[ Java面试题 ] 集合篇

2037
来自专栏云霄雨霁

查找----基于有序数组

1680
来自专栏AILearning

Map集合

Collection |--List:元素是有序的,元素可以重复,因为该集合体系有索引 |--ArrayList:底层的数据结构使用的是数据结构。特点:查询...

2386

扫码关注云+社区

领取腾讯云代金券