Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 寻找最近非互质数_Java_Algorithm - Fatal编程技术网

Java 寻找最近非互质数

Java 寻找最近非互质数,java,algorithm,Java,Algorithm,给定一个数组,我需要找到最近的非互质数的索引(即GCD(Ai,Aj)>1,对于数组中的任何Ai和Aj,I!=j)例如,让数组 [2 17 4 6 10] 答案是 [3 -1 4 3 4] 我使用二进制GCD方法编写了这个暴力代码(即O(n^2)),这不是很有效。我想知道是否有更快的方法尤其是O(NlogN) import java.io.OutputStream; 导入java.io.IOException; 导入java.io.InputStream; 导入java.io.PrintWr

给定一个数组,我需要找到最近的非互质数的索引(即GCD(Ai,Aj)>1,对于数组中的任何Ai和Aj,I!=j)例如,让数组

[2 17 4 6 10]
答案是

[3 -1 4 3 4] 
我使用二进制GCD方法编写了这个暴力代码(即O(n^2)),这不是很有效。我想知道是否有更快的方法尤其是O(NlogN)

import java.io.OutputStream;
导入java.io.IOException;
导入java.io.InputStream;
导入java.io.PrintWriter;
导入java.util.StringTokenizer;
导入java.io.IOException;
导入java.io.BufferedReader;
导入java.io.InputStreamReader;
导入java.io.InputStream;
/**
*使用CHelper插件构建
*实际解决方案在顶部
*
*@作者Mayur Kulkarni
*/
公共班机{
公共静态void main(字符串[]args){
InputStream InputStream=System.in;
OutputStream OutputStream=System.out;
BladeReader in=新BladeReader(inputStream);
PrintWriter out=新的PrintWriter(outputStream);
GCDPuz解算器=新的GCDPuz();
解算器。解算(1,输入,输出);
out.close();
}
静态类GCDPuz{
公共静态int gcd(int p,int q){
如果(q==0)返回p;
如果(p==0)返回q;
//p和q偶数
如果((p&1)==0&(q&1)==0)返回gcd(p>>1,q>>1)>1,q);
//p是奇数,q是偶数
否则如果((q&1)==0)返回gcd(p,q>>1);
//p和q奇数,p>=q
否则如果(p>=q)返回gcd((p-q)>>1,q);
//p和q奇数,p>1);
}
公共整数互质(整数p,整数q){
如果(p%2==0&&q%2==0){
返回2;
}else如果(p==q+1 | | q==p+1){
返回1;
}否则{
返回gcd(p,q);
}
}
public void solve(int testNumber、BladeReader-in、PrintWriter-out){
int size=in.nextInt();
int[]arr=in.readIntArray(大小);
int[]ans=新的int[size];
对于(int i=0;i1)返回j;
}
返回-1;
}
私有int findLeft(int[]arr,int i){
if(arr[i]==-1)返回-1;
对于(int j=i-1;j>=0;j--){
如果(互质(arr[i],arr[j])>1)返回j;
}
返回-1;
}
私有int-findNearestIndex(int-one,int-oneDist,int-two,int-twoDist){
if(oneDist==-1&&twoDist==-1)返回-1;
if(oneDist==-1)返回2;
if(twoDist==-1)返回一个;
if(oneDist==twoDist){
返回Math.min(一,二);
}
返回oneDist
如果您知道您的数字的最大值,并且有能力保存一个素数列表,那么对平均/随机情况进行因式分解可能是一个更好的解决方案。否则,最坏情况下的复杂性仍然是O(N*N)-认为最坏情况下的“它们都是素数”

方法:

  • 将它们分解并存储一个
    Map[N]
    +
    int closestNeigh[]
  • 取一个系数,然后
    O(N)
    为每个系数确定包含该系数的最近值(将涉及前缀/sufix和)
  • 从所有因子映射中删除该因子
  • 考虑下一个因素。仅当新索引最近时才调整最近邻索引

这可能会在
O(N*)
这一行上带来一些“解脱”,但同样,如果
==N(所有素数),那么它仍然是O(N*N)

如果你愿意进入因子分解,你可以遍历列表,从左边开始一次,对每个数字进行因子分解,散列每个新素数的索引(以素数为键),更新已经看到的每个素数的索引,当然,注意t
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author Mayur Kulkarni
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        BladeReader in = new BladeReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        GCDPuz solver = new GCDPuz();
        solver.solve(1, in, out);
        out.close();
    }

    static class GCDPuz {
        public static int gcd(int p, int q) {
            if (q == 0) return p;
            if (p == 0) return q;
            // p and q even
            if ((p & 1) == 0 && (q & 1) == 0) return gcd(p >> 1, q >> 1) << 1;
                // p is even, q is odd
            else if ((p & 1) == 0) return gcd(p >> 1, q);
                // p is odd, q is even
            else if ((q & 1) == 0) return gcd(p, q >> 1);
                // p and q odd, p >= q
            else if (p >= q) return gcd((p - q) >> 1, q);
                // p and q odd, p < q
            else return gcd(p, (q - p) >> 1);
        }

        public int coprime(int p, int q) {
            if (p % 2 == 0 && q % 2 == 0) {
                return 2;
            } else if (p == q + 1 || q == p + 1) {
                return 1;
            } else {
                return gcd(p, q);
            }
        }

        public void solve(int testNumber, BladeReader in, PrintWriter out) {
            int size = in.nextInt();
            int[] arr = in.readIntArray(size);
            int[] ans = new int[size];
            for (int i = 0; i < arr.length; i++) {
                if (arr[i] == 1) {
                    ans[i] = -1;
                    continue;
                }
                int left = i == 0 ? -1 : findLeft(arr, i);
                int right = i == arr.length - 1 ? -1 : findRight(arr, i);
                int leftDist = left == -1 ? -1 : i - left;
                int rightDist = right == -1 ? -1 : right - i;
                int anss = findNearestIndex(left, leftDist, right, rightDist);
                ans[i] = anss == -1 ? -1 : anss + 1;
            }
            printa(ans, out);
        }

        private void printa(int[] ans, PrintWriter out) {
            StringBuilder sb = new StringBuilder();
            for (int an : ans) {
                sb.append(an).append(" ");
            }
            out.println(sb.toString());
        }

        private int findRight(int[] arr, int i) {
            if (arr[i] == -1) return -1;
            for (int j = i + 1; j < arr.length; j++) {
                if (coprime(arr[i], arr[j]) > 1) return j;
            }
            return -1;
        }

        private int findLeft(int[] arr, int i) {
            if (arr[i] == -1) return -1;
            for (int j = i - 1; j >= 0; j--) {
                if (coprime(arr[i], arr[j]) > 1) return j;
            }
            return -1;
        }

        private int findNearestIndex(int one, int oneDist, int two, int twoDist) {
            if (oneDist == -1 && twoDist == -1) return -1;
            if (oneDist == -1) return two;
            if (twoDist == -1) return one;
            if (oneDist == twoDist) {
                return Math.min(one, two);
            }
            return oneDist < twoDist ? one : two;
        }
    }

    static class BladeReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public BladeReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public int[] readIntArray(int size) {
            int[] array = new int[size];
            for (int i = 0; i < size; i++) {
                array[i] = nextInt();
            }
            return array;
        }
    }
}