Java 如果我的int数组包含超过65535个元素,为什么最大和子数组会停止工作?
我有一个程序,它根据用户输入生成一个数组(数组可以是降序、升序和两种类型的随机数组),然后使用暴力、分治和动态规划计算最大子数组和。它似乎工作得很好,最高可达65535。在那之后,每一个总数都是不同的,这是不应该发生的。35535是2乘以16减1的幂,所以我想知道我是否达到了极限。当我打印数组时,它似乎打印得很好,所以我认为问题不在于数组没有正确生成 这是主要课程:Java 如果我的int数组包含超过65535个元素,为什么最大和子数组会停止工作?,java,arrays,sorting,Java,Arrays,Sorting,我有一个程序,它根据用户输入生成一个数组(数组可以是降序、升序和两种类型的随机数组),然后使用暴力、分治和动态规划计算最大子数组和。它似乎工作得很好,最高可达65535。在那之后,每一个总数都是不同的,这是不应该发生的。35535是2乘以16减1的幂,所以我想知道我是否达到了极限。当我打印数组时,它似乎打印得很好,所以我认为问题不在于数组没有正确生成 这是主要课程: public class MainClass { public static void main(String[] args)
public class MainClass {
public static void main(String[] args) {
int n = Integer.parseInt(args[1]);
int[] maxsubarray1;
maxsubarray1 = new Generator(n,args[3]).getArray();
int[] maxsubarray2 = Arrays.copyOf(maxsubarray1,maxsubarray1.length);
int[] maxsubarray3 = Arrays.copyOf(maxsubarray1,maxsubarray1.length);
System.out.println(Arrays.toString(maxsubarray1));
solver solver = new solver();
int solution;
//if (args[5].equalsIgnoreCase("bruteforce")){
long startTime = System.currentTimeMillis();
solution = solver.bruteforce(maxsubarray1, n);
System.out.println("__________BRUTE FORCE________\nThe sum of the array is "+solution);
long endTime = System.currentTimeMillis() - startTime;
System.out.println(endTime);
//}
//if (args[5].equalsIgnoreCase("divideconquer")){
long startTime2 = System.currentTimeMillis();
int solutiondivideconquer = solver.divideconquer(maxsubarray2, 0, n);
System.out.println("__________DIVIDE AND CONQUERE________\nThe sum of the array is "+ solutiondivideconquer);
long endTime2 = System.currentTimeMillis() - startTime2;
System.out.println(endTime2);
//}
//if (args[5].equalsIgnoreCase("dynprog")){
long startTime3 = System.currentTimeMillis();
int solutiondynprog = solver.dynprog(maxsubarray3, n);
System.out.println("__________DYNAMIC PROGRAMMING________\nThe sum of the array is "+ solutiondynprog);
long endTime3 = System.currentTimeMillis() - startTime3;
System.out.println(endTime3);
//}
}
}
这是发电机代码:
import java.util.concurrent.ThreadLocalRandom;
public class Generator {
int size;
String type;
int[] generatedArray;
public Generator(int mysize, String mytype){
size = mysize;
type = mytype;
generatedArray = new int[size];
}
public void ascending(){
for(int i = 0; i < this.size; i++)
generatedArray[i] = i+1;
}
public void descending(){
for(int i = this.size -1; i >= 0; i--)
generatedArray[i] = i+1;
}
public void random(){
for(int i = 0; i <= this.size -1; i++)
generatedArray[i] = ThreadLocalRandom.current().nextInt(-10*this.size, 10*this.size);
}
public void randominter(){
for(int i = 0; i <= this.size -1; i++)
if (i % 2 == 0)
generatedArray[i] = ThreadLocalRandom.current().nextInt(1, 10*this.size);
else if (i % 2 == 1)
generatedArray[i] = ThreadLocalRandom.current().nextInt(-10*this.size, -1);
}
public int[] getArray(){
if (type.equalsIgnoreCase("descending")){
this.descending();
return generatedArray;
}
if (type.equalsIgnoreCase("ascending")){
this.ascending();
return generatedArray;
}
if (type.equalsIgnoreCase("random")){
this.random();
return generatedArray;
}
if (type.equalsIgnoreCase("randominter")){
this.randominter();
return generatedArray;
}
return null;
}
}
import java.util.concurrent.ThreadLocalRandom;
公共类生成器{
整数大小;
字符串类型;
int[]生成阵列;
公共生成器(int mysize,String mytype){
大小=神秘化;
类型=mytype;
GenerateArray=新整数[大小];
}
公共空间(英文){
for(int i=0;i=0;i--)
生成阵列[i]=i+1;
}
公屋{
对于(int i=0;ii是错误的,如果Array[i]=i+1
,则可能是溢出错误,因为总和是length*(min+max)/2
>Integer.max\u VALUE我复制了您的代码,将所有int更改为long,并且工作正常。还更改了n=Integer.parseInt(args[0])
,而不是n=Integer.parseInt(args[1])
然后我调用了我的程序,比如program\u name 1000 random
我检查了excel,只有bruteforce出错。我已将Integer.MIN_值
更改为Long.MIN_值
,并将int sum
更改为Long sum
Main.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
public class Main {
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
long[] maxsubarray1;
maxsubarray1 = new Generator(n, args[1]).getArray();
long[] maxsubarray2 = Arrays.copyOf(maxsubarray1, maxsubarray1.length);
long[] maxsubarray3 = Arrays.copyOf(maxsubarray1, maxsubarray1.length);
System.out.println(Arrays.toString(maxsubarray1));
solver solver = new solver();
long solution;
//if (args[5].equalsIgnoreCase("bruteforce")){
long startTime = System.currentTimeMillis();
solution = solver.bruteforce(maxsubarray1, n);
System.out.println("__________BRUTE FORCE________\nThe sum of the array is " + solution);
long endTime = System.currentTimeMillis() - startTime;
System.out.println(endTime);
//}
//if (args[5].equalsIgnoreCase("divideconquer")){
long startTime2 = System.currentTimeMillis();
long solutiondivideconquer = solver.divideconquer(maxsubarray2, 0, n);
System.out.println("__________DIVIDE AND CONQUERE________\nThe sum of the array is " + solutiondivideconquer);
long endTime2 = System.currentTimeMillis() - startTime2;
System.out.println(endTime2);
//}
//if (args[5].equalsIgnoreCase("dynprog")){
long startTime3 = System.currentTimeMillis();
long solutiondynprog = solver.dynprog(maxsubarray3, n);
System.out.println("__________DYNAMIC PROGRAMMING________\nThe sum of the array is " + solutiondynprog);
long endTime3 = System.currentTimeMillis() - startTime3;
System.out.println(endTime3);
//}
}
}
solver.java
public class solver {
//brute force algorithm with complexity O(n^2)
long bruteforce(long array[], int n){
long max = Long.MIN_VALUE;
//We go throght all the elements of the list and we try all the
//posible combinations with all the other elements
for (int i = 0; i < n; i++){
long sum = 0;
for (int j = i; j < n ; j++){
//we add the an element in the sum
sum += array[j];
//we check if the sum with the new element is greater that the value we had before
if(sum > max){
//if it's greater, it becomes the new value
max = sum;
}
}
}
//we return the maximum value we have found
return max;
}
//to implement the divide and conquer algorithm we have to take into account the
// maximum subarray can have elements in the right subarray and in the left subarray
long maxCrossingSum(long array[], long l, long m, long h){
long sum = 0;
long left_sum = Integer.MIN_VALUE;
//Has the elements on the left part of the arrray
for ( int i = (int)m; i >= l; i--){
sum = sum + array[i];
if( sum > left_sum ){
left_sum = sum;
}
}
sum = 0;
long right_sum = 0;
//Has the elements in the right part of the array
for ( int j = (int)m+1; j <= h; j++){
sum = sum + array [j];
if (sum > right_sum){
right_sum = sum;
}
}
//returns the sun of the elements on the left and the right of the array
return left_sum + right_sum;
}
//returns the sum of the maximum subarray
long maxSubarraySum(long array[], long l, long h){
if(l == h)
return array[1];
long m = (l + h)/2;
//checks which is the maximum between left and right
long maxBetweenLeftRight = max(maxSubarraySum(array, l, m), maxSubarraySum(array, m+1,h));
long crossing = maxCrossingSum(array, l, m,h-1);
//retrns the maximum between one of the sides and the crossing sum
return max(maxBetweenLeftRight, crossing);
}
//divide and conquere algorithm with complexity O(nlogn)
//only made to make it more understandable from the main
//can call maxSubarraySum and it would be the same
long divideconquer (long array[], int l, int h){
return maxSubarraySum(array, l, h);
}
//dynamic programming algorithm with complexity O(n)
long dynprog(long array[], int n){
long a = array[0];
long b = array[0];
//for all the elements checks if the sum was better until the
//step before or adding the element
for (int i = 1 ; i < n; i++){
a= max (a+ array[i], array[i]);
b= max(b, a);
}
return b;
}
private long max(long a, long b) {
if (a > b ) return a;
else return b;
}
}
公共类求解器{
//复杂度为O(n^2)的蛮力算法
长蛮力(长数组[],int n){
长最大值=长最小值;
//我们浏览了列表中的所有元素,并尝试了所有
//所有其他元素的可能组合
对于(int i=0;i最大值){
//如果它更大,它将成为新值
最大值=总和;
}
}
}
//我们返回找到的最大值
返回最大值;
}
//为了实现分治算法,我们必须考虑
//最大子阵列可以在右侧子阵列和左侧子阵列中包含元素
长最大交叉数(长数组[],长l,长m,长h){
长和=0;
长左_和=Integer.MIN_值;
//元素位于阵列的左侧
对于(int i=(int)m;i>=l;i--){
总和=总和+数组[i];
如果(总和>左总和){
左和=和;
}
}
总和=0;
长右_和=0;
//元素位于数组的右侧
对于(int j=(int)m+1;j右和){
右和=和;
}
}
//返回数组左侧和右侧元素的太阳
返回左求和+右求和;
}
//返回最大子数组的和
长最大子阵列和(长阵列[],长l,长h){
如果(l==h)
返回数组[1];
长m=(l+h)/2;
//检查左右之间的最大值
long maxBetweenLeftRight=max(MaxSubraySum(数组,l,m),MaxSubraySum(数组,m+1,h));
长交叉=最大交叉(阵列,l,m,h-1);
//重新计算其中一条边与交叉总和之间的最大值
返回最大值(maxBetweenLeftRight,交叉);
}
//复杂度为O(nlogn)的分而治之算法
//只是为了让它从总体上更容易理解
//可以调用MaxSubraySum,它将是相同的
长除法征服(长数组[],整数l,整数h){
返回最大子数组和(数组,l,h);
}
//复杂度为O(n)的动态规划算法
长dynprog(长数组[],int n){
长a=数组[0];
长b=数组[0];
//对于所有元素,检查总和是否更好,直到
//在添加元素之前或之后执行步骤
对于(int i=1;ib)返回a;
否则返回b;
}
}
Generator.java
import java.util.concurrent.ThreadLocalRandom;
public class Generator {
int size;
String type;
long[] generatedArray;
public Generator(int mysize, String mytype) {
size = mysize;
type = mytype;
generatedArray = new long[size];
}
public void ascending() {
for (int i = 0; i < this.size; i++)
generatedArray[i] = i + 1;
}
public void descending() {
for (int i = this.size - 1; i >= 0; i--)
generatedArray[i] = i + 1;
}
public void random() {
for (int i = 0; i <= this.size - 1; i++)
generatedArray[i] = ThreadLocalRandom.current().nextInt(-10 * this.size, 10 * this.size);
}
public void randominter() {
for (int i = 0; i <= this.size - 1; i++)
if (i % 2 == 0)
generatedArray[i] = ThreadLocalRandom.current().nextInt(1, 10 * this.size);
else if (i % 2 == 1)
generatedArray[i] = ThreadLocalRandom.current().nextInt(-10 * this.size, -1);
}
public long[] getArray() {
if (type.equalsIgnoreCase("descending")) {
this.descending();
return generatedArray;
}
if (type.equalsIgnoreCase("ascending")) {
this.ascending();
return generatedArray;
}
if (type.equalsIgnoreCase("random")) {
this.random();
return generatedArray;
}
if (type.equalsIgnoreCase("randominter")) {
this.randominter();
return generatedArray;
}
return null;
}
}
import java.util.concurrent.ThreadLocalRandom;
公共类生成器{
整数大小;
字符串类型;
长[]生成阵列;
公共生成器(int mysize,String mytype){
大小=神秘化;
类型=mytype;
GenerateArray=新长[尺寸];
}
公共空间(英文){
for(int i=0;i=0;i--)
生成阵列[i]=i+1;
}
公屋{
对于(int i=0;i),它只是停止,没有错误消息、stacktrace或任何东西?65535是无符号short
的最大值。不,它打印所有内容,只是总和不一致,而不管方法是什么,所有三个总和都应该相同。第二个if inif(i%2==0)else if(i%2==1)
是无用的,因为一旦它进入else部分,i%2
将始终是1,所以只需else
就足够了问题在于n
大于65535,或者数组的值更大
import java.util.concurrent.ThreadLocalRandom;
public class Generator {
int size;
String type;
long[] generatedArray;
public Generator(int mysize, String mytype) {
size = mysize;
type = mytype;
generatedArray = new long[size];
}
public void ascending() {
for (int i = 0; i < this.size; i++)
generatedArray[i] = i + 1;
}
public void descending() {
for (int i = this.size - 1; i >= 0; i--)
generatedArray[i] = i + 1;
}
public void random() {
for (int i = 0; i <= this.size - 1; i++)
generatedArray[i] = ThreadLocalRandom.current().nextInt(-10 * this.size, 10 * this.size);
}
public void randominter() {
for (int i = 0; i <= this.size - 1; i++)
if (i % 2 == 0)
generatedArray[i] = ThreadLocalRandom.current().nextInt(1, 10 * this.size);
else if (i % 2 == 1)
generatedArray[i] = ThreadLocalRandom.current().nextInt(-10 * this.size, -1);
}
public long[] getArray() {
if (type.equalsIgnoreCase("descending")) {
this.descending();
return generatedArray;
}
if (type.equalsIgnoreCase("ascending")) {
this.ascending();
return generatedArray;
}
if (type.equalsIgnoreCase("random")) {
this.random();
return generatedArray;
}
if (type.equalsIgnoreCase("randominter")) {
this.randominter();
return generatedArray;
}
return null;
}
}