优化阵列的分区



我正在解决一个编程挑战问题,但我的解决方案是给出大数字的超时/错误。谁能帮我优化我的解决方案?

问题:

您将获得一个由 N 个整数组成的数组 A。现在,您需要修复 X,以使以下两个值之间的差异最小:

  1. A[1] * A[2] * A[3] * ......... * A[X]
  2. A[X+1] * A[X+2] * ........... * A[N]

如果 X 的值更多,则打印最小的值。

约束:

  • 1 <= 1 <= 10^5
  • 1 <= A[i] <= 10^18

输入:

  • 第一行包含整数 N(表示大小(
  • 第二行包含空格分隔的数字(用于数组(
import java.util.*;
public class Main
{
    public static void main(String[] args) {
        Scanner s=new Scanner(System.in)
        int size=Integer.parseInt(s.nextLine);
        long arr[]=new long[size];
        for(int i=0;i<=size;i++){
            arr[i]=s.nextLong();
        }   
        long part1=1,part2=1;
        long diff=1;long minIndex=0;long minNo=0;
        
        for(int k=0;k<size-1;k++){
            part1=1;part2=1;
            //minIndex=k;
            for (int i=0;i<=k ; i++){
                part1=part1*arr[i];
            } 
            for(int j=k+1;j<=size;j++){
                part2=part2*arr[j];
            }
            //System.out.println(part1+"---"+part2);
            diff=Math.abs(part1-part2);
            if(k==0){
                minNo=diff;
                minIndex=k;
            }
            //System.out.println(diff);
            if(minNo>diff){
                
                 minNo=diff;
                 minIndex=k;
            }
               
            
        }
        System.out.println("MinNo: "+minNo+" Index: "+minIndex);
        
        
        
    }
}

我正在针对此输入进行测试

5
9090909090909009 780009090900909 898989898898898 98998 9999776765576765

答案应该是 2(如果从零开始计数,那么 1(,但我的代码给出 4。

虽然@Mukesh Prajapati提出的答案有效,但仍然有一种更快更好的方法可以做到这一点。

您可以使用log来缩短值,因此您只需在log计算中添加或减去值,因为现在加法意味着乘法,减法意味着除法。现在,您的问题简化为在数组中查找左侧元素之和最接近右侧元素的点。

存储累积总和以便快速查找。这使您能够快速计算数组的左和和右和。最终的最小差值以ans为单位,而索引则以变量为单位index

void partition(int n, vector<double> &a) {
    double total = 0; vector<double> sum_array_a;
    for(auto &x: a) {
            x = log10(x);
            total += x;
            sum_array_a.push_back(total);
    }
    double ans = INFINITY, index = -1;
    for(int i = 0; i < n; i++) {    // Check for all points if you can split here
            double left = sum_array_a[i];
            double right = total - left;    // Right side sum of elements
            double diff = abs(left - right);
            if(diff < ans) {
                    ans = diff;
                    index = i;
            }
    }
    printf("%f", index);
}

没有必要一次又一次地计算子数组的乘法。这就是您收到超时错误的原因。您正在使用Long来存储乘法,这将导致错误的答案,您需要使用BigInteger。下面的方法只会做一次乘法。之后,您可以简单地迭代并找出它们之间的差异。

import java.math.BigInteger;
import java.util.Scanner;
public class ParitionArray {
    public static void main(String[] args){
        Scanner s=new Scanner(System.in);
        int size=Integer.parseInt(s.nextLine());
        long arr[]=new long[size];
        for(int i=0;i<size;i++){
            arr[i]=s.nextLong();
        }
        long minIndex=0;
        BigInteger minNo=BigInteger.ZERO;
        BigInteger[] prefixedMult = new BigInteger[size];
        prefixedMult[0] = BigInteger.valueOf(arr[0]);
        for(int k =1; k< size; k++){
            prefixedMult[k] = prefixedMult[k-1].multiply(BigInteger.valueOf(arr[k]));
        }
        for(int k=0;k<size;k++){
            BigInteger part1 = prefixedMult[k]; //multiplication of A[1]*A[2]A[3].........*A[k]
            BigInteger part2 = prefixedMult[size-1].divide(part1);    //multiplication of A[k+1]A[k+2]...........*A[size]
            BigInteger diff = part1.subtract(part2).abs();
            if(k==0){
                minNo=diff;
                minIndex=k;
            }
            //System.out.println(diff);
            if(minNo.compareTo(diff)==1){
                minNo=diff;
                minIndex=k;
            }
        }
        System.out.println("MinNo: "+minNo+" Index: "+minIndex);
    }
}

输入:

5
2
8
6
5
3

输出:

MinNo: 74 Index: 1

我发现@AndrewScott答案很有帮助。下面是它在 Java 中的等效实现:

 public static void main(String[] args){
        Scanner s=new Scanner(System.in);
        int size=Integer.parseInt(s.nextLine());
        long arr[]=new long[size];
        for(int i=0;i<size;i++){
            arr[i]=s.nextLong();
        }
        long minIndex=0;
        Double minNo=Double.MAX_VALUE;
        Double[] prefixedMult = new Double[size];
        prefixedMult[0] = Math.log10((double)arr[0]);
        for(int k =1; k< size; k++){
            prefixedMult[k] = prefixedMult[k-1] + Math.log10((double)arr[k]);
        }
        for(int k=0;k<size;k++){
            Double part1 = prefixedMult[k]; //multiplication of A[1]*A[2]A[3].........*A[k]
            Double part2 = prefixedMult[size-1] - (part1);    //multiplication of A[k+1]A[k+2]...........*A[size]
            Double diff = Math.abs(part1 - part2);
            if(minNo > diff){
                minNo=diff;
                minIndex=k;
            }
        }
        System.out.println("MinNo: "+minNo+" Index: "+minIndex);
    }

最新更新