如何在Java中以更优化的方式生成数字组合?

如何在Java中以更优化的方式生成数字组合?,java,numbers,combinations,triplet,Java,Numbers,Combinations,Triplet,我有一个问题陈述,要求将3个不同的数字传递给一个方法,并检查哪3个数字满足某个约束 这是我的代码,但我想知道有没有更优化的方法来检查哪组三元组满足某个约束,而不是创建嵌套循环 import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class Solution { static List l = new ArrayList(); static int geomet

我有一个问题陈述,要求将3个不同的数字传递给一个方法,并检查哪3个数字满足某个约束

这是我的代码,但我想知道有没有更优化的方法来检查哪组三元组满足某个约束,而不是创建嵌套循环

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Solution
{

    static List l = new ArrayList();

    static int geometricTrick(String s)
    {
        int count = 0;

        for (int i = 0; i < s.length(); i++)
        {
            for (int j = 0; j < s.length(); j++)
            {
                for (int k = 0; k < s.length(); k++)
                {
                    if (is1stConstraintTrue(s, i, j, k) && is2ndConstraintTrue(i, j, k))
                    {
                        l.add(new Triplet(i, j, k));
                    }
                }
            }
        }

        count = l.size();

        return count;

    }

    static boolean is2ndConstraintTrue(int i, int j, int k)
    {
        boolean retVal = false;

        double LHS = Math.pow((j + 1), 2);

        double RHS = (i + 1) * (k + 1);

        if (LHS == RHS)
            retVal = true;
        else
            retVal = false;

        return retVal;
    }

    static boolean is1stConstraintTrue(String s, int i, int j, int k)
    {
        boolean retVal = false;

        char[] localChar = s.toCharArray();

        if (localChar[i] == 'a' && localChar[j] == 'b' && localChar[k] == 'c')
        {
            retVal = true;
        }

        return retVal;
    }

    static class Triplet
    {
        public int i, j, k;

        public Triplet(int i, int j, int k)
        {
            this.i= i;
            this.j= j;
            this.k= k;
        }
    }
    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        String s = in.next();
        int result = geometricTrick(s);
        System.out.println(result);

    }
}
import java.util.ArrayList;
导入java.util.List;
导入java.util.Scanner;
公共类解决方案
{
静态列表l=新的ArrayList();
静态整数几何单击(字符串s)
{
整数计数=0;
对于(int i=0;i
以下是一些提示:

  • 通过乘法计算平方比使用
    pow

  • String::toCharray()
    非常昂贵。它将所有字符复制到一个新数组中。每次你叫它。不要叫它多次

  • 如果结果是三元组的数量,则不需要构建列表。您甚至不需要创建
    Triple
    实例。数一数

  • 如果需要迭代所有的组合,嵌套循环不是低效的


  • 为您提供一个简单而“愚蠢”的解决方案,不使用这些内部循环

    让我们使用类似于
    迭代器的工厂。这将使用条件语句“隐藏”循环

    public class TripletFactory{
    
        final int maxI, maxJ, maxK;
        int i, j ,k;
    
        public TripletFactory(int i, int j, int k){
            this.maxI = i;
            this.maxJ = j;
            this.maxK = k;
        }
    
        public Triplet next(){
            if(++k > maxK){
                k = 0;
                if(++j > maxJ){
                    j = 0;
                    if(++i > maxI){
                        return null;
                    }
                }
            }
            return new Triplet(i,j,k);
        }
    }   
    
    这样,您只需在一个循环中获得一个新的
    三元组
    ,直到
    null
    实例

    TripletFactory fact = new TripletFactory(2, 3 ,5);
    
    Triplet t = null;
    while((t = fact.next()) != null){
        System.out.println(t);
    }
    //no more Triplet
    
    你想怎么用就怎么用

    然后,您必须更新约束方法,以获取一个
    三元组
    ,并使用getter检查实例

    这可能是一种
    Triplet
    的方法,让它顺便验证自己

    注:

    我使用了与
    迭代器
    相同的符号,因为我们可以实现
    迭代器
    Iterable
    来使用如下符号:

    for(Triplet t : factory){
        ...
    }
    

    您介绍的简单方法具有立方时间复杂性(对于
    -循环有三个嵌套的
    )。如果您的输入中多次出现
    'a'
    'b'
    'c'
    ,那么首先确定所有
    'a'
    'b'
    'c'
    的索引,然后仅在该集合上检查第二个条件可能是值得的

    import java.util.ArrayList;
    import java.util.List;
    
    public class Main {
    
        public static List<Integer> getAllOccurrences(String input, char of) {
            List<Integer> occurrences = new ArrayList<Integer>();
            char[] chars = input.toCharArray();
    
            for (int idx = 0; idx < chars.length; ++idx) {
                if (of == chars[idx]) {
                    occurrences.add(idx);
                }
            }
    
            return (occurrences);
        }
    
        static List<Triplet> geometricTrick(String input){
            List<Integer> allAs = getAllOccurrences(input, 'a');
            List<Integer> allBs = getAllOccurrences(input, 'b');
            List<Integer> allCs = getAllOccurrences(input, 'c');
            List<Triplet> solutions = new ArrayList<Triplet>();
    
            // reorder the loops, so that the c-loop is the innermost loop (see
            // below why this is useful and how it is exploited).
            for (int a : allAs) {
                for (int c : allCs) {
                    // calculate lhs as soon as possible, no need to recalculate the
                    // same value multiple times
                    final int lhs = ((a + 1) * (c + 1));
    
                    for (int b : allBs) {
                        final int rhs = ((b + 1) * (b + 1));
                        if (lhs > rhs) {
                           continue;
                        }
    
                        /* else */ if (lhs == rhs) {
                            solutions.add(new Triplet(a, b, c));
                        }
    
                        // by construction, the b-values are in ascending or der.
                        // Thus if the rhs-value is larger or equal to the
                        // lhs-value, we can skip all other rhs-values. for this
                        // lhs-value.
    
                        // if (lhs <= rhs) {
                            break;
                        // }
                    }
                }
            }
            return (solutions);
        }
    
        static class Triplet {
    
            public final int i;
            public final int j;
            public final int k;
    
            public Triplet(int i, int j, int k) {
                this.i = i;
                this.j = j;
                this.k = k;
            }
        }
    }
    
    import java.util.ArrayList;
    导入java.util.List;
    公共班机{
    公共静态列表getAllOccurrences(字符串输入,字符){
    列表出现次数=新建ArrayList();
    char[]chars=input.toCharArray();
    对于(int idx=0;idx右侧){
    持续
    }
    /*else*/if(lhs==rhs){
    添加(新的三联体(a,b,c));
    }
    //通过构造,b值以升序或降序排列。
    //因此,如果rhs值大于或等于
    //lhs值,我们可以跳过所有其他rhs值
    //lhs值。
    
    //如果(lhs您的满意度标准是什么?
    double
    比较不好。将其更改回
    int
    。这看起来像是一个双重问题。首先,您要查找输入中的字符
    'a'
    'b'
    'c'
    。接下来,您想知道字符所在的索引是否满足某些c要求条件。我将首先查找所有出现的
    'a'
    'b'
    'c'字符串
    并检查每个三元组