给定一个数 N 和一个排序数组 A,检查 A 中是不是有两个数的乘积为 N

Posted

技术标签:

【中文标题】给定一个数 N 和一个排序数组 A,检查 A 中是不是有两个数的乘积为 N【英文标题】:Given a number N and a sorted array A, check if there are two numbers in A whose product is N给定一个数 N 和一个排序数组 A,检查 A 中是否有两个数的乘积为 N 【发布时间】:2021-09-06 12:24:13 【问题描述】:

给定一个数字 N 和一个排序数组 A,设计一个算法 - 使用 分而治之 方法 - 检查是否存在索引 i 和索引 j 使得 A[i]*A[j] == N(如果存在则返回 1,如果不存在则返回 0)。

我很难以所需的(递归)方式进行。我想我只想出了一个可能的解决方案的一部分,但即使在那里我也不能 100% 确定它是否正确:我认为如果数组的第一个元素和中心元素之间的乘积大于 N,那么我正在寻找的数字(如果存在)肯定在数组的前半部分,所以我可以递归地调用该部分的函数,就像这样(我正在使用 C):

int productN(int A[], int i, int j, int N)

    // missing base case

    int m = (i+j)/2;
    
    if(A[i]*A[m] > N)
        return productN(A, i, m, N);
     else
        // do something else
    

int main()

    int A[]=1, 2, 3, 4, 5;
    printf("%d\n", productN(A, 0, 4, 15));  // initial value for i and j are the first and last index of the array

    return 0;


除此之外,我被困住了,我什至想不出一个基本案例,所以任何帮助将不胜感激,谢谢。

编辑: 根据您非常有用的答案,使用二进制搜索,我想我明白了:

int productN(int A[], int i, int j, int N)
    
    int m = (i+j)/2;    // central element of the current array
    
    int x;
    for(x=i; x<=m; x++)
        if(N%A[x]==0 && binarySearch(A, m, j, N/A[x]))
            return 1;
    
        
    if(i!=j)
        if(productN(A, i, m, N) || productN(A, m+1, j, N))
            return 1;
    
    
    return 0;


好吃吗?可以更好吗?

编辑:自从我问这个问题以来已经有一段时间了,但我写了另一个解决方案,更易于阅读。如果有人感兴趣,我会留在这里。

int productN(int A[], int i, int j, int N, int size)
    
    if(i==j)        // base case
        if(N%A[i]==0)
            return binarySearch(A, 0, size-1, N/A[i]);
        else
            return 0;
    
        
    int m = (i+j)/2; 
    
    if((N%A[m])==0)
        if(binarySearch(A, 0, size-1, N/A[i]))
            return 1;
    
    
    return productN(A, i, m, N, size) || productN(A, m+1, j, N, size);


【问题讨论】:

如果你知道a[i]N,你就知道a[j]的值是多少;您只需要查看该值是否存在于数组中。由于数组已排序,这表明二进制搜索... 你需要使用分而治之吗?如果数组已排序并且所有涉及的数字都是正数并且我们可以忽略溢出,则将 i 设置为 0 并将 j 设置为最后一个元素的索引。如果A[i]*A[j] == N,你就完成了(成功)。如果j &lt;= i,你就完成了(失败)。如果A[i]*A[j] &lt; N,则增加i,以使产品更大(因为A 已排序)。如果A[i]*A[j] &gt; N,则递减j,使产品更小。然后重复。 (将解决方案扩展到非正值留作练习。) 【参考方案1】:

使用分而治之,您可以使用类似于归并排序算法的方法。正如 cmets 所建议的,有更简单的方法。但如果分而治之是必须的,这就足够了。 (我不精通C,所以我只会写算法)

def productN(arr):
    x = len(arr)
    left_half = arr[0:x/2]
    right_half = arr[x/2:]
    if productN(left_half) or productN(right_half):
        return True
    for i in left_half:
        if N%i==0 and binary_search(right_half, N/i):
            return True
    return False

【讨论】:

考虑用 C 编写

以上是关于给定一个数 N 和一个排序数组 A,检查 A 中是不是有两个数的乘积为 N的主要内容,如果未能解决你的问题,请参考以下文章

编写一个函数swap,将指定数组按照从小到大的顺序排序,

LEETCODE刷题 二维数组查找

给定一整型数组,若数组中某个下标值大的元素值小于某个下标值比它小的元素值,称这是一个反序

合并排序数组

逆序对 (树状数组 | | 归并排序

C语言新手 给定一段连续的正整数,请判断其中素数的个数