-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathZeroSumArray.java
More file actions
131 lines (103 loc) · 4.11 KB
/
ZeroSumArray.java
File metadata and controls
131 lines (103 loc) · 4.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package com.company;
import java.util.ArrayList;
import java.util.Collections;
// Given range and n generate a list containing n values in the interval {-range, range} that add up to zero
public class ZeroSumArray {
private int n;
private int range;
private ArrayList <Integer> nlist = new ArrayList<Integer>();
private ArrayList <Integer> numbers= new ArrayList<Integer>();
public ZeroSumArray(int n, int range) {
this.n = n;
this.range = range;
}
private int getRandom(int lower, int upper) {
return (int)(Math.random() * ((upper-lower)+1)+lower);
}
private void initvalidnums(){
for (int i=-range; i<=range; i++){
numbers.add(i);
}
}
private void fill(){
int i=1;
int zeroindex = range;
int rand;
while (i<=n/4+1){
rand = getRandom(1,numbers.size()-1-zeroindex);
nlist.add(numbers.remove(zeroindex+rand));
nlist.add(numbers.remove(zeroindex-rand));
i++;
zeroindex--;
}
}
private int findnextavailable(int value){
int inc = value/Math.abs(value); //According to the value received by the method, establishes if the next available number is meant to be higher or lower
int iterator = value - range*inc - inc; //Establishes what is the limit value which will still verify the condition, ex: for range=10, [-10...10], for value = -3 the limit value is 7, as anything higher will make it impossible to have -range + iterator = -3
boolean indexnotfound = true;
while (Math.abs(iterator)<=range && indexnotfound){
iterator = iterator + inc;
if (numbers.contains(iterator)) indexnotfound = false;
}
return numbers.indexOf(iterator);
}
private void replace(int index){
int valuetoreplace = nlist.get(index);
boolean notreplaced = true;
ArrayList <Integer> sub; //auxiliary arraylist that will hold a subarray of numbers, containing the range of values that can lead to the desired replacement, as defined by findnextavailable() method
if (valuetoreplace > 0) sub = new ArrayList<Integer>(numbers.subList(findnextavailable(valuetoreplace),numbers.size()));
else{
sub = new ArrayList<Integer>(numbers.subList(0,findnextavailable(valuetoreplace)+1));
}
while (notreplaced && sub.size()>1){
int rand = getRandom(0,sub.size()-1);
int aux = valuetoreplace-sub.get(rand);
//if aux = 8 - (-1) = 9 then we need to check if sub contains 9, and if it does, we know that we can replace 8 with 9 and -1 in nlist.
//aux!=sub.get(rand) is there to avoid 8 - 4 = 4, where 4 would be added to nlist twice.
if (sub.contains(aux) && aux!=sub.get(rand)){
nlist.remove(Integer.valueOf(valuetoreplace));
nlist.add(sub.get(rand));
nlist.add(aux);
numbers.add(valuetoreplace);
Collections.sort(numbers);
numbers.remove(sub.get(rand));
numbers.remove(Integer.valueOf(aux));
notreplaced=false;
}
sub.remove(rand);
}
}
private void create(int delta){
for (int i=1; i<=range; i++){
nlist.add(i);
nlist.add(-i);
}
for (int i=1; i<=delta; i++){
int rand = getRandom(0,(nlist.size()-1)/2)*2;
nlist.remove(rand);
nlist.remove(rand);
}
if (n%2!=0) nlist.add(0);
}
public ArrayList<Integer> generate() {
if (n<1 || n>range*2+1){
throw new IllegalArgumentException();
}
nlist.clear();
numbers.clear();
if (n==1){
nlist.add(0);
return nlist;
}
if (n >= range*2 -1) {
create((int) Math.ceil ((double) (range*2-n)/2));
} else {
initvalidnums();
fill();
while (nlist.size() != n) {
replace(getRandom(0, nlist.size() - 1));
}
}
return nlist;
}
}