我有一个问题陈述,需要将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);
}
}
答案 0 :(得分:0)
以下是一些提示:
通过乘法计算平方将比使用pow
String::toCharray()
很贵。它将所有字符复制到一个新数组中。每次你打电话。不要多次打电话。
如果结果是三元组的数量,则不需要构建列表。您甚至不需要创建Triple
个实例。算一算吧。
如果需要迭代所有组合,嵌套循环效率不高。
答案 1 :(得分:0)
为您提供一个简单的&#34;愚蠢的&#34;不使用那些内循环的解决方案。
让我们像Iterator
一样使用工厂。这将隐藏&#34;使用条件语句循环。
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);
}
}
这样,您只需要获得一个新的Triple
,直到一个循环中的null
个实例
TripletFactory fact = new TripletFactory(2, 3 ,5);
Triplet t = null;
while((t = fact.next()) != null){
System.out.println(t);
}
//no more Triplet
并按照您的意愿使用它。
然后,您必须更新约束方法以获取Triplet
并使用getters检查实例。
这可能是Triplet
允许它顺便验证自己的方法。
注意:
我使用了与Iterator
相同的表示法,因为我们可以实现Iterator
和Iterable
来使用如下符号:
for(Triplet t : factory){
...
}
答案 2 :(得分:0)
您提出的天真方法具有三次时间复杂度(三个嵌套for
- 循环)。如果您在输入中出现过多次'a'
,'b'
和'c'
,那么首先确定所有'a'
的索引可能是值得的, 'b'
&{39}和'c'
&#39;然后只检查您的第二个条件。
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;
}
}
}
在给定char
内搜索所有出现的String
需要O(n)(方法getAllOccurrences(...)
),调用它三次不会改变复杂性(3 * n \ in上))。迭代a
,b
和c
的所有可能组合需要#a
*#b
*#c
时间,其中#{{ 1}},#a
和#b
会计入c
,a
&{39}和b
& #39;在c
中。这使得总时间复杂度为O(n +#input
*#a
*#b
)。
请注意,最糟糕的情况是时间复杂,即如果您的字符串的1/3由c
组成,则1/3由a
组成,并且1 / 3由b
组成,仍然是立方体。