Java 打印给定数字的所有唯一因子组合

Java 打印给定数字的所有唯一因子组合,java,algorithm,recursion,time-complexity,factors,Java,Algorithm,Recursion,Time Complexity,Factors,打印一个正整数的所有唯一因子组合的最有效算法是什么。例如,如果给定的数字是24,那么输出应该是 24*1 12*2 8*3 6*4 6*2*2 4*3*2 3*2*2*2 这里请注意,当6*4被打印时,4*6就不会被打印。所以基本上这是一个在不考虑顺序的情况下获取唯一子集的问题(一种看待问题的方法)。但目标是拥有一个运行最快的函数,因此将因子存储在数据结构中以进行进一步操作可能需要更多的时间。我已经尝试了我的算法,并在下面粘贴了我的代码,但它似乎没有给我想要的结果,我在递归调用中犯了一些错误。

打印一个正整数的所有唯一因子组合的最有效算法是什么。例如,如果给定的数字是24,那么输出应该是

24*1
12*2
8*3
6*4
6*2*2
4*3*2
3*2*2*2
这里请注意,当6*4被打印时,4*6就不会被打印。所以基本上这是一个在不考虑顺序的情况下获取唯一子集的问题(一种看待问题的方法)。但目标是拥有一个运行最快的函数,因此将因子存储在数据结构中以进行进一步操作可能需要更多的时间。我已经尝试了我的算法,并在下面粘贴了我的代码,但它似乎没有给我想要的结果,我在递归调用中犯了一些错误。你能帮我想出一个有效的方法吗

public static void printfact(int num){
        int temp=0;
        for(int i=num-1;i>=num/2;i--){
            if(num % i == 0){
                temp = num/i;
                System.out.println(temp + " * " + i);
                if(isprime(i)==false){
                    System.out.print(temp + " * ");
                    printfact(i);
                }
            }
        }
}
1) 如果
i
i>num/2
,则
num%i==num-i
。(很容易证明。)因此,您的
for
循环将无意义地检查所有大于
num/2
的整数,
if
语句只会成功一次,其中
temp==2
。我认为那不是你想要的

2) 在您修复了这个问题后,递归可能需要生成很多答案。但是您只打印一次
temp*
。所以输出看起来有点古怪

3)
isprime
是不必要的
num
始终是一个合法的因子,无论它是否为素数,只要您遵循以下要点

4) 最后,您需要找出如何避免多次打印相同的因式分解。简单的解决方案是只生成因子单调非递增的因子分解(如您的示例所示)。为了做到这一点,递归需要生成具有某个最大因子(这将是以前发现的因子)的因子分解。因此递归函数应该(至少)有两个参数:因子数和允许的最大因子。(您还需要处理我在第4点中提到的问题。)

下面的Python代码(我相信)确实解决了这个问题,但它仍然进行了许多不必要的划分。与python风格不同的是,它打印每个分解,而不是充当生成器,因为这样更容易翻译成Java

# Uses the last value in accum as the maximum factor; a cleaner solution
# would have been to pass max_factor as an argument.
def factors(number, accum=[]):
  if number == 1:
    print '*'.join(map(str, accum))
  else:
    if accum:
      max_factor = min(accum[-1], number)
    else:
      max_factor = number
    for trial_factor in range(max_factor, 1, -1):
      remnant = number / trial_factor
      if remnant * trial_factor == number:
        factors(remnant, accum + [trial_factor,])

可以为
语句优化
。例如,一旦您计算了
剩余量
,您就知道下一个
剩余量
必须至少大于一个,因此当
剩余量
很小时,您可以跳过一组
试用系数
值。

此代码找到一个数字的所有系数,对它们进行排序(本地和全局):


尝试这种递归方法,该方法还需要另外两个输入,即一个字符串来携带for循环中i的当前值,以执行后续还原,以及一个临时int来知道何时不打印重复的反转,即8*3和3*8

public static void printFactors(int number, String parentFactors, int parentVal) {
    int newVal = parentVal;
    for (int i = number - 1; i >= 2; i--) {

        if (number % i == 0) {
            if (newVal > i) {
                newVal = i;
            }
            if (number / i <= parentVal && i <= parentVal
                    && number / i <= i) {
                System.out.println(parentFactors + i + "*" + number / i);
                newVal = number / i;
            }

            if (i <= parentVal) {
                printFactors(number / i, parentFactors + i + "*", newVal);
            }
        }

    }

}
publicstaticvoidprintfactors(int-number,stringparentfactors,int-parentVal){
int newVal=parentVal;
对于(int i=number-1;i>=2;i--){
如果(编号%i==0){
如果(newVal>i){
newVal=i;
}
if(数字/i
vector GetAllFactors(无符号整数)
{
矢量因子;
对于(int i=2;i
bool isprime(int n){

对于(inti=2;i,这里是我基于@rici的想法的解决方案

def因数(数字,最大因数=sys.maxint):
结果=[]
系数=最小值(数字/2,最大系数)
当系数>=2时:
如果数字%因子==0:
除数=数字/因数
如果除数[[12,2],[8,3],[6,4],[6,2,2],[4,3,2],[3,2,2]]
打印系数(157)#->[]

我有一个在C/C++中没有递归、排序或堆栈的解决方案

#include <vector>
#include <iostream>

// For each n, for each i = n-1 to 2, try prod = prod*i, if prod < N.

int
g(int N, int n, int k)
{
        int i = k;
        int prod = n;
        std::vector<int> myvec;

        myvec.push_back(n);
        while (i > 1) {
                if (prod * i == N) {
                        prod = prod*i;
                        myvec.push_back(i);
                        for (auto it = myvec.begin();
                                it != myvec.end(); it++) {
                                std::cout << *it << ",";
                        }
                        std::cout << std::endl;
                        return i;
                } else if (prod * i < N) {
                        prod = prod*i;
                        myvec.push_back(i);
                } else { i--;}
        }

        return k;
}

void
f(int N)
{
        for (int i = 2; i <= N/2; i++) {
                int x = g(N, i, i-1);
                // Extract all possible factors from this point
                while (x > 0) {
                        x = g(N, i, x-1);
                }
        }
}

int
main()
{
        f(24);

        return 0;
}

我想出了这个,似乎很容易阅读和理解。希望它有帮助

def getFactors(num):

    results = []

    if num == 1 or 0:
        return [num]

    for i in range(num/2, 1, -1):

        if (num % i == 0):
            divisor = num / i

            if(divisor <= i):
                results.append([i, divisor])

            innerResults = getFactors(divisor)

            for innerResult in innerResults:
                if innerResult[0] <= i:
                    results.append([i] + innerResult)

    return results
def getFactors(num):
结果=[]
如果num==1或0:
返回[num]
对于范围内的i(num/2,1,-1):
如果(num%i==0):
除数=num/i
如果(除数
#包括
使用名称空间std;
int n;
//prod=组合向量中因子的当前乘积
//curr=电流系数
void fun(int curr、int prod、向量组合)
{
if(prod==n)
{

对于(int j=0;j谢谢问题编辑建议Sanjeevi认为您需要:找到所有因子后。6和4都不是24(或任何其他数字)的基本因子,因为它们不是,嗯……素数。@Aubin这是正确的标题,它不是关于打印素数因子,而是关于所有因子的组合。看看我给出的示例。确切地说,我不确定是否可以在递归减少较大的e之前,用一个二级字符串参数传入该函数,该参数携带要打印的先前因子元素(例如,如果数字为40,则为10*4,然后将10和4减少为5*2*2*2等)。但是我们第一次如何调用该函数。但是我在可视化它时遇到了问题。不,您不需要同时减少10和4。第一个因子
5
应该稍后显示。因此,您应该生成
10*4
10*2*2
,然后
8*5
,然后
5*4*2
5*2*2
。(当然,这是在其他因子分解之后,
40
20*2
)因此,问题是如何有效地决定递归中哪些是合理的第一因素,而不需要做很多不必要的模运算。是的,但是如何递归地处理这个问题。你能提供一个样例代码吗?@ CurryIim5:添加了一些Python代码,你可以考虑伪代码。谢谢RICI,我修改了一点MO。re和我自己的回答。让我知道你的想法。谢谢你的解决方案。是的,这与我第一次做的差不多,但我们需要消除重复组合。不生成重复比事后消除它们要有效得多。正如我所说,关键是始终生成单调的非重复组合
vector<unsigned int> GetAllFactors(unsigned int number)
{
    vector<unsigned int> factors;

    for (int i = 2; i <= number; i++)
    {
        if (number % i == 0)
        {
            factors.push_back(i);
        }
    }

    return factors;
}

void DoCombinationWithRepetitionFactors(vector<unsigned int> allFactors, unsigned currentProduct, unsigned targetProduct, vector<unsigned int> currentFactorSet, unsigned currentFactorIndex)
{
    if (currentProduct == targetProduct)
    {
        for (auto a : currentFactorSet)
        {
            cout << a << " , ";
        }

        cout << endl;

        return;
    }


    for (int i = currentFactorIndex; i < allFactors.size(); i++)
    {
        if (currentProduct * allFactors[i] <= targetProduct)
        {
            currentFactorSet.push_back(allFactors[i]);
            DoCombinationWithRepetitionFactors(allFactors, currentProduct * allFactors[i], targetProduct, currentFactorSet, i);
            currentFactorSet.pop_back();
        }
    }
}
bool isprime(int n){
for(int i=2; i<=sqrt(n); i++)
    if(n%i==0)
        return false;
return true;
}

void printprime(int n){

int i,j,y=n;

while(y%2==0){
    cout<<"2 * ";
    y/=2;
}

for(i=3; i<=sqrt(y); i+=2){
    while(y%i==0){
        cout<<i<<" * ";
        y/=i;
    }
}

if(y>2)
    cout<<y;
}

void allfacs(int n){

int i;
unordered_set<int> done;

for(i=2; i<sqrt(n); i++){
    if(n%i==0){
        cout<<i<<" * "<<n/i<<endl;

        if(!isprime(i) && done.find(i) == done.end()){
            done.insert(i);
            printprime(i);
            cout<<n/i<<endl;
        }
        if(!isprime(n/i) && done.find(n/i) == done.end()){
            done.insert(n/i);
            cout<<i<< " * ";
            printprime(n/i);
            cout<<endl;
        }
    }
}
}
#include <vector>
#include <iostream>

// For each n, for each i = n-1 to 2, try prod = prod*i, if prod < N.

int
g(int N, int n, int k)
{
        int i = k;
        int prod = n;
        std::vector<int> myvec;

        myvec.push_back(n);
        while (i > 1) {
                if (prod * i == N) {
                        prod = prod*i;
                        myvec.push_back(i);
                        for (auto it = myvec.begin();
                                it != myvec.end(); it++) {
                                std::cout << *it << ",";
                        }
                        std::cout << std::endl;
                        return i;
                } else if (prod * i < N) {
                        prod = prod*i;
                        myvec.push_back(i);
                } else { i--;}
        }

        return k;
}

void
f(int N)
{
        for (int i = 2; i <= N/2; i++) {
                int x = g(N, i, i-1);
                // Extract all possible factors from this point
                while (x > 0) {
                        x = g(N, i, x-1);
                }
        }
}

int
main()
{
        f(24);

        return 0;
}
$ ./a.out
    3,2,2,2,
    4,3,2,
    6,4,
    6,2,2,
    8,3,
    12,2,
def getFactors(num):

    results = []

    if num == 1 or 0:
        return [num]

    for i in range(num/2, 1, -1):

        if (num % i == 0):
            divisor = num / i

            if(divisor <= i):
                results.append([i, divisor])

            innerResults = getFactors(divisor)

            for innerResult in innerResults:
                if innerResult[0] <= i:
                    results.append([i] + innerResult)

    return results
#include<bits/stdc++.h>
using namespace std;
int n;
// prod = current product of factors in combination vector
// curr = current factor
void fun(int curr, int prod, vector<int> combination )
{
    if(prod==n)
    {
        for(int j=0; j<combination.size(); j++)
        {
            cout<<combination[j]<<" ";
        }
        cout<<endl; 
        return;
    }

    for(int i=curr; i<n; i++)
    {
        if(i*prod>n) break;
        if(n%i==0)
        {
            combination.push_back(i);
            fun(i, i*prod, combination);
            combination.resize(combination.size()-1);
        }
    }
}

int main()
{
    cin>>n;
    vector<int> combination;
    fun(2, 1, combination);
    cout<<1<<" "<<n;
    return 0;
}