C++ 求两对数的乘积绝对差最小

C++ 求两对数的乘积绝对差最小,c++,algorithm,C++,Algorithm,问题: 给定一个整数num,找出绝对差中最接近的两个整数,其乘积等于num+1或num+2 按任意顺序返回两个整数 我试过这个: vector<int> closestDivisors(int num) { if(num == 1) return {1,2}; int first = num + 1, second = num + 2; std::vector<int> result(2); aut

问题:

给定一个整数num,找出绝对差中最接近的两个整数,其乘积等于num+1或num+2

按任意顺序返回两个整数

我试过这个:

vector<int> closestDivisors(int num) {
    
    if(num == 1)
        return {1,2};
    int first = num + 1, second = num + 2;
    std::vector<int> result(2);        
    auto vec1 = properDivisors(first);
    auto vec2 = properDivisors(second);
    std::map<int, std::pair<int,int>> m;
    int min_k1 = INT_MAX;
    for(auto it1 : vec1)
    {
        for(auto it2 : vec1)
        {
            if (it1 * it2 == first)
            {
                min_k1 = abs(it1-it2);
                m[min_k1] = {it1, it2};
            }
        }
    }
    
    int min_k2 = INT_MAX;
    for(auto it1 : vec2)
    {
        for(auto it2 : vec2)
        {
            if (it1 * it2 == second)
            {
                min_k2 = abs(it1-it2);
                m[min_k2] = {it1, it2};
            }
        }
    }

    for(auto it : m)
    {
        result[0] = it.second.first;
        result[1] = it.second.second;
        if(result.size() == 2)
            break;
    }
    
    
    

    return result;
}


std::vector<long long> properDivisors(int number) {
   std::vector<long long> divisors ;
   for ( int i = 1 ; i < number / 2 + 1 ; i++ )
      if ( number % i == 0 )
     divisors.push_back( i ) ;
   return divisors ;
}
向量闭因子(int num){
如果(num==1)
返回{1,2};
int first=num+1,second=num+2;
std::向量结果(2);
auto vec1=属性指示器(第一);
auto vec2=属性指示器(秒);
std::map m;
int min_k1=int MAX;
用于(自动it1:vec1)
{
用于(自动it2:vec1)
{
如果(it1*it2==第一个)
{
min_k1=abs(it1-it2);
m[min_k1]={it1,it2};
}
}
}
int min_k2=int MAX;
用于(自动it1:vec2)
{
用于(自动it2:vec2)
{
如果(it1*it2==秒)
{
min_k2=abs(it1-it2);
m[min_k2]={it1,it2};
}
}
}
用于(自动it:m)
{
结果[0]=it.second.first;
结果[1]=it.second.second;
if(result.size()==2)
打破
}
返回结果;
}
标准::向量属性指示器(整数){
向量除数;
对于(int i=1;i

但我总是超过时间限制。有没有更有效的方法来实现这一点?

向量的使用可能会使它比需要的慢得多。我将按以下方式处理

lo
设置为
1
并将
hi
设置为
num+1
。这是获取两个整数的起点,两个整数相乘为所需值之一(相距较近的是
1
num+2
,因此可以忽略这种可能性)

然后,只需将
lo
hi
向对方移动(直到它们交叉),检查产品是否等于所需值。事实上,这两个数字正在接近,这意味着任何以后的成功都将使它们比以前的更接近

唯一棘手的一点是数字如何相互接近,但这比你想象的要简单。如果乘积小于
num+1
,则减小
hi
将意味着它离所需值更远,因此在这种情况下,您需要增加
lo

另一方面,大于
num+2
的乘积意味着您应该减少
hi
(增加
lo
将使乘积更高,从而远离期望值)

如果它等于
num+1
num+2
,则可以选择其中一个选项。这不重要的原因是因为
lo+1
hi
之间的绝对差异与
lo
hi-1
之间的绝对差异相同(a)


例如,下面是一个Python程序,它显示了它的实际功能:

num = int(input("Number: "))
lo = 1
hi = num + 1
found = None
while lo <= hi: # Make this '<' if numbers must be different.
    prod = lo * hi
    if prod == num + 1 or prod == num + 2:
        found = (lo, hi)
        mark = ' *'
    else:
        mark = ""
    print(f"Low = {lo}, high = {hi}, product = {prod}{mark}")
    if prod < num + 1:
        lo += 1
    else:
        hi -= 1
print(found)

正如在评论中指出的,这只处理积极的输入。您也可以通过更改以下内容来满足负输入:

lo = 1
hi = num + 1
致:

这包含了解决方案的积极和消极领域,增加了一点额外的时间,但仍然非常快



(a) 我只对我的数学有99.99%的把握,因此,如果有人能提供一个反例,我很乐意编辑答案(或者甚至删除它,如果我不能解决它,尽管可能会在边缘案例中发现任何存在的问题,因此可能可以通过一些简单的预检查来解决)。让我知道。

这是C++中的代码。< /P>
#include <bits/stdc++.h>
using namespace std;
void print_vector(vector<auto> v){
   cout << "[";
   for(int i = 0; i<v.size(); i++){
       if(v.size() - i == 1) {
           cout << v[i];
       } else {
          cout << v[i] << ", ";
       }
   }
   cout << "]"<<endl;
}
class Solution {
public:
   vector <int> getDiv(int x){
      int diff = INT_MAX;
      vector <int> ret(2);
      for(int i = 1; i * i <= x; i++){
         if(x % i == 0){
            int a = i;
            int b = x / i;
            int newDiff = abs(a - b);
            if(newDiff < diff){
               diff = newDiff;
               ret[0] = a;
               ret[1] = b;
            }
         }
      }
      return ret;
   }
   vector<int> closestDivisors(int num) {
      vector <int> op1 = getDiv(num + 1);
      vector <int> op2 = getDiv(num + 2);
      return abs(op1[0] - op1[1]) <= abs(op2[0] - op2[1]) ? op1 : op2;
   }
};
main(){
   Solution ob;
   print_vector(ob.closestDivisors(8));
}

// Output [3,3]
#包括
使用名称空间std;
无效打印向量(向量

Javascript代码

let num = 8; //Input

function getFactors(num) {
  let factors = [1];
  for (let i = 2; i <= Math.sqrt(num); i++) {
    if (num % i === 0) {
      factors.push(i);
      factors.push(num / i);
    }
  }
  factors.push(num);
  return factors;
}

(function getSmallAbsDiff() {
  const factorsNplusOne = getFactors(num + 1).sort((a, b) => a - b);
  const factorsNplusTwo = getFactors(num + 2).sort((a, b) => a - b);

  const minOne = factorsNplusOne[factorsNplusOne.length / 2 - 1];
  const maxOne = factorsNplusOne[factorsNplusOne.length / 2];
  const minTwo = factorsNplusTwo[factorsNplusTwo.length / 2 - 1];
  const maxTwo = factorsNplusTwo[factorsNplusTwo.length / 2];

  maxOne - minOne < maxTwo - minTwo ? console.log(`[${maxOne}, ${minOne}]`) : console.log(`[${maxTwo}, ${minTwo}]`); // Output
})();
let num=8;//输入
函数getFactors(num){
设因子=[1];
for(设i=2;i a-b);
constfactorsnplustwo=getFactors(num+2).sort((a,b)=>a-b);
const minOne=factorsNplusOne[factorsNplusOne.length/2-1];
const maxOne=factorsNplusOne[factorsNplusOne.length/2];
const minTwo=factorsNplusTwo[factorsNplusTwo.length/2-1];
const maxTwo=factorsNplusTwo[factorsNplusTwo.length/2];
maxOne-minOne

您有没有可能用自己选择的语言纠正这种逻辑?它适用于负数?(我没有检查,但这是明显的未检查边缘情况)我怀疑从
sqrt(num)
开始工作可以更有效地完成这项工作outwards@Donnie:说得好。您可以通过初始化来处理负数
lo=-num-1
hi=num+1
如果lo>hi:(lo,hi)=(hi,lo)
。我将把它添加到答案中,而不是从lo=1和hi=num+1开始,并将lo和hi相互移动,从lo开始,您将获得更好的性能≈ 你好≈ √num和移动lo和hi使其彼此远离。这样,你一找到解决方案就可以退出。我发现问题陈述非常模糊,绝对值最接近的两个数字是什么意思?那句话可以用多种方式解释。。。
#include <bits/stdc++.h>
using namespace std;
void print_vector(vector<auto> v){
   cout << "[";
   for(int i = 0; i<v.size(); i++){
       if(v.size() - i == 1) {
           cout << v[i];
       } else {
          cout << v[i] << ", ";
       }
   }
   cout << "]"<<endl;
}
class Solution {
public:
   vector <int> getDiv(int x){
      int diff = INT_MAX;
      vector <int> ret(2);
      for(int i = 1; i * i <= x; i++){
         if(x % i == 0){
            int a = i;
            int b = x / i;
            int newDiff = abs(a - b);
            if(newDiff < diff){
               diff = newDiff;
               ret[0] = a;
               ret[1] = b;
            }
         }
      }
      return ret;
   }
   vector<int> closestDivisors(int num) {
      vector <int> op1 = getDiv(num + 1);
      vector <int> op2 = getDiv(num + 2);
      return abs(op1[0] - op1[1]) <= abs(op2[0] - op2[1]) ? op1 : op2;
   }
};
main(){
   Solution ob;
   print_vector(ob.closestDivisors(8));
}

// Output [3,3]
let num = 8; //Input

function getFactors(num) {
  let factors = [1];
  for (let i = 2; i <= Math.sqrt(num); i++) {
    if (num % i === 0) {
      factors.push(i);
      factors.push(num / i);
    }
  }
  factors.push(num);
  return factors;
}

(function getSmallAbsDiff() {
  const factorsNplusOne = getFactors(num + 1).sort((a, b) => a - b);
  const factorsNplusTwo = getFactors(num + 2).sort((a, b) => a - b);

  const minOne = factorsNplusOne[factorsNplusOne.length / 2 - 1];
  const maxOne = factorsNplusOne[factorsNplusOne.length / 2];
  const minTwo = factorsNplusTwo[factorsNplusTwo.length / 2 - 1];
  const maxTwo = factorsNplusTwo[factorsNplusTwo.length / 2];

  maxOne - minOne < maxTwo - minTwo ? console.log(`[${maxOne}, ${minOne}]`) : console.log(`[${maxTwo}, ${minTwo}]`); // Output
})();