zoukankan      html  css  js  c++  java
  • 剑指offer 42.和为S的两个数字

    题目描述

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

    输出描述:

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

    思路:

    两个指针,分别从前后同时扫描数组,如果和大于 sum, 后面的数组往中间移一个,如果小于 sum, 前面的数组往中间移一位
    这题主要要注意第一次碰到相加等于 sum 的两个数的乘积就是最小的,不能被题目坑了

    找到的第一组(相差最大的)就是乘积最小的。
    可以这样证明:https://www.nowcoder.com/questionTerminal/390da4f7a00f44bea7c2f3d19491311b?f=discussion
    考虑x+y=C(C是常数),x*y的大小。
    不妨设y>=x,y-x=d>=0,
    即y=x+d, 2x+d=C, x=(C-d)/2, 
    x*y=x(x+d)=(C-d)(C+d)/4=(C^2-d^2)/4,
    也就是x*y是一个关于变量d的二次函数,对称轴是y轴,开口向下。d是>=0的,d越大, x*y也就越小
     1 import java.util.ArrayList;
     2 public class Solution {
     3      public static ArrayList<Integer> FindNumbersWithSum(int [] array, int sum) {
     4         ArrayList<Integer> list = new ArrayList<Integer>();
     5         if(array == null || array.length == 0){
     6             return list;
     7         }
     8 
     9          // 其实第一次碰到相加等于 sum 的两个数的乘积就是最小的,不能被题目坑了
    10 
    11         // 两个指针,分别从前后同时扫描数组
    12         int i = 0, j = array.length - 1;
    13         int a = 0, b = 0;
    14         int mul = 1 << 30;
    15         while(i < j){
    16             // 如果和大于 sum, 后面的数组往中间移一个
    17             int temp = array[i] + array[j];
    18             if(temp == sum){
    19                 list.add(array[i]);
    20                 list.add(array[j]);
    21                 break;
    22             }else if(temp > sum){
    23                 j--;
    24             }else{
    25                 i++;
    26             }
    27         }
    28        return list;
    29     }
    30 }
  • 相关阅读:
    编译impala2.0.0
    CentOS 7 安装Boost 1.61
    CentOS 6.4 编译安装LLVM3.3,Clang和Libc++
    批量修改dos文件到unix
    git win7 dos下设置代理
    vim源码编译启用python
    一张图看懂天津市教育云服务平台
    关于git中Pageant开机启动且自动关联秘钥
    Windows 10安装pip方法
    大数据中心的业务研发路线
  • 原文地址:https://www.cnblogs.com/hi3254014978/p/12601464.html
Copyright © 2011-2022 走看看