问题:
给出一个整数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 ;
}
但是我不断超过时间限制。有没有更有效的方法来实现这一目标?
答案 0 :(得分:2)
使用向量可能会使它变得慢得多。我将按照以下方式进行处理。
将lo
设置为1
,将hi
设置为num + 1
。这是获得两个整数的起点,两个整数相乘成所需的值之一(与1
和num + 2
比较接近,因此您可以忽略这种可能性)。
然后只需将lo
和hi
彼此相对移动(直到它们交叉),以检查乘积以查看其是否等于所需值。这两个数字接近的事实意味着,以后的任何成功都将使它们比以前的更紧密。
唯一棘手的问题是数字之间的相互关系,但这比您想象的要简单。如果乘积小于num + 1
,则减小hi
意味着它会进一步偏离期望值,因此在这种情况下,您需要增大lo
。< / p>
另一方面,乘积大于num + 2
表示您应减少hi
(增加lo
会使乘积升高,从而远离期望值)。 / p>
如果等于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)
进行几次跑步:
Number: 3
Low = 1, high = 4, product = 4 *
Low = 1, high = 3, product = 3
Low = 2, high = 3, product = 6
Low = 2, high = 2, product = 4 *
(2, 2)
Number: 10
Low = 1, high = 11, product = 11 *
Low = 1, high = 10, product = 10
Low = 2, high = 10, product = 20
Low = 2, high = 9, product = 18
Low = 2, high = 8, product = 16
Low = 2, high = 7, product = 14
Low = 2, high = 6, product = 12 *
Low = 2, high = 5, product = 10
Low = 3, high = 5, product = 15
Low = 3, high = 4, product = 12 *
Low = 3, high = 3, product = 9
(3, 4)
Number: 100
Low = 1, high = 101, product = 101 *
Low = 1, high = 100, product = 100
Low = 2, high = 100, product = 200
Low = 2, high = 99, product = 198
: : : (lots of stuff irrelevant to final result)
Low = 6, high = 18, product = 108
Low = 6, high = 17, product = 102 *
Low = 6, high = 16, product = 96
Low = 7, high = 16, product = 112
Low = 7, high = 15, product = 105
Low = 7, high = 14, product = 98
Low = 8, high = 14, product = 112
Low = 8, high = 13, product = 104
Low = 8, high = 12, product = 96
Low = 9, high = 12, product = 108
Low = 9, high = 11, product = 99
Low = 10, high = 11, product = 110
Low = 10, high = 10, product = 100
(6, 17)
正如评论中指出的那样,这仅处理正面输入。您还可以通过更改以下内容来满足负面输入的要求:
lo = 1
hi = num + 1
收件人:
lo = -num - 1
hi = num + 1
if lo > hi:
(lo, hi) = (hi, lo)
这将解决方案的正面和领域括起来,增加了一些额外的时间,但仍然非常快。
(a)我对这里的数学只有99.99%的把握,因此,如果有人可以提供反例,我很乐意编辑答案(甚至删除答案,如果尽管在极端情况下很可能会发现存在的任何问题,但我无法解决它,因此可以通过一些简单的预检查就可以解决)。让我知道。
答案 1 :(得分:0)
这是c ++中的代码。
#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]
You can run the above code here
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
})();