Iterate over consecutive object pairs in an ArrayList - java

I want to get pairs of objects from an ArrayList so I can perform calculations between the elements of each object. Ideally it should iterate over pairs of objects. For example in a List with {obj1, obj2, obj3, obj4} it should go over {obj1,obj2}, {obj2,obj3} and {obj3,obj4}.
What I have tried so far is as follows.
public class Sum {
public ArrayList<Double> calculateSum(ArrayList<Iter> iter) {
ListIterator<Iter> it = iter.listIterator();
ArrayList<Double> sums = new ArrayList<>();
while (it.hasNext()) {
Iter it1 = it.next();
Iter it2;
if(it.hasNext()){
it2 = it.next();
} else { break; }
double sum = it1.getValue() + it2.getValue();
sums.add(sum);
}
return sums;
}
}
Here, it just iterates as {obj1,obj2} and {obj3,obj4}. How can I fix this?
All help is greatly appreciated. Thanks!

A very normal loop, except that you need to loop up to list.size() - 1, the before last element of the array.
public ArrayList<Double> calculateSum(ArrayList<Iter> list) {
ArrayList<Double> sums = new ArrayList<>();
for (int i = 0; i < list.size() - 1; i++) {
double sum = list.get(i).getValue() + list.get(i + 1).getValue();
sums.add(sum);
}
return sums;
}
EDIT
Using an iterator in this case will not be faster than doing a normal loop and just makes the logic unnecessarily complicated and can easily introduce bugs.

A little modification to Davide's answer
for (int i = 0; i < list.size() - 1; i ++) {
sums.add(list.get(i) + list.get(i+1));
}
Because the OP wanted {obj1, obj2} {obj2, obj3} ...etc
Using a iterator
itr = list.iterator();
while(itr.hasNext()) {
Double x = itr.next();
if(itr.hasNext()){
x+= itr.next();
sum.add(x);}
itr.previous();
}
This is not recommended.

Simply use a for loop and stop at element before last one.
for (int i = 0; i < iter.size() - 1; i++) {
Iter first = iter.get(i);
Iter second = iter.get(i + 1);
// Your code here
}

public static ArrayList<Double> calculateSum(ArrayList<Iter> iter) {
ListIterator<Iter> it = iter.listIterator();
ArrayList<Double> sums = new ArrayList<>();
if (it.hasNext()) {
double prev = it.next().getValue();
while (it.hasNext()) {
double current = it.next().getValue();
double sum = prev + current;
sums.add(sum);
prev = current;
}
}
return sums;
}

Try this :-
public ArrayList<Double> calculateSum(ArrayList<Iter> inputList) {
ArrayList<Double> sums = new ArrayList<Double>();
int inputSize = inputList.size(); // size should be saved as an int , instead of calling size() over the list again and again in for loop
int incVar = 1; // 1 incremented value
double sum = 0.0d;
for(int i = 0; incVar < inputSize; i++,incVar++){
sum = inputList.get(i).getValue() + inputList.get(incVar).getValue();
sums.add(sum);
}
return sums;
}

Related

Find the Maximum difference between two Same Numbers in an unsorted array of integers in best Time Complexity [Java]

static int solution(int[] A) {
int N = A.length;
int result = 0;
Map<Integer, List<Integer>> map = new TreeMap<>();
for (int i = 0; i < N; i++) {
List<Integer> list = map.getOrDefault(A[i], new ArrayList<>());
list.add(i);
map.put(A[i], list);
}
for (Map.Entry<Integer, List<Integer>> entry : map.entrySet()) {
List<Integer> list = map.get(entry.getKey());
Collections.sort(list);
result = Math.max(result, (list.get(list.size() - 1) - list.get(0)));
}
return result;
}
With this above solution we can solve the problem but it is not O(N) time complexity. So I am looking for an optimized solution for this problem in Java.
// Collections.sort(list);//Removing this line makes O(NlogK) to O(N) time complexity
static int solution(int[] A) {
int N = A.length;
int result = 0;
Map<Integer, List<Integer>> map = new HashMap<>();
for (int i = 0; i < N; i++) {
List<Integer> list = map.getOrDefault(A[i], new ArrayList<>());
list.add(i);
map.put(A[i], list);
}
for (Map.Entry<Integer, List<Integer>> entry : map.entrySet()) {
List<Integer> list = map.get(entry.getKey());
result = Math.max(result, (list.get(list.size() - 1) - list.get(0)));
}
return result;
}
One of the solution is loop through all elements and keep track of only first and last occurence as follow:
class Pair<F, S> {
F first;
S second;
constrcutor(F first, S second) {
this.first = first;
this.second = second;
}
}
static int solution(int arr[]) {
// Pair.first will contain the first occurrence and Pair.second will contain the last occurrence of number
HashMap<Integer, Pair<Integer, Integer>> minMaxMap = new HashMap<>();
for (int index = 0; index < arr.length; index++) {
Pair<Integer, Integer> existingValue = minMaxMap.get(arr[index]);
if (existingValue == null) {
minMaxMap.put(arr[index], new Pair<Integer, Integer>(index, index));
} else {
existingValue.second = index; // update the Pair.second to latest value.
}
}
int result = 0;
for (Pair<Integer, Integer> pair : minMaxMap.values()) {
int difference = pair.second - pair.first;
if (difference > result) {
result = difference;
}
}
return result;
}
In your solution, since we are using list, it requires more memory in case the array contains a lot of duplicate element. By avoiding list, you can even reduce the memory footprint.
I think this looks like an efficient solution - it doesn't use any collections and doesn't need to loop through all values. It checks for pair at the maximum distance (same numbers at both array ends), then maximum distance-1 and so on, only until the pair is found.
static int solution(int[] A) {
for (int i = 0; i < A.length; i++) {
for (int j = 0; j < i; j++) {
if (A[j] == A[j + A.length - i])
return A.length - i;
}
}
return -1; //-1 stands for no equal numbers
}

How to sort a LinkedHashMap by value without Collections.sort()?

I'm trying to write a selection sort method for a LinkedHashMap/ArrayList but I'm having issues and I'm not sure what's wrong. It compiles but doesn't actually sort the list. I'm trying to sort in descending order by value. Any help would be appreciated.
public static List sort(LinkedHashMap<String, Integer> words) {
List<Map.Entry<String, Integer>> entries = new ArrayList<>(words.size());
entries.addAll(words.entrySet());
int max;
for(int i = 0; i < entries.size(); i++) {
max = entries.get(i).getValue();
for(int j = i + 1; j < entries.size(); j++) {
if (entries.get(j).getValue().compareTo(entries.get(max).getValue()) > 0) {
max = entries.get(j).getValue();
}
}
if(max != i) {
Map.Entry temp1 = entries.get(i);
entries.set(entries.get(i).getValue(), entries.get(max));
entries.set(entries.get(max).getValue(), temp1);
}
}
return entries;
}
You're code is essentially correct, you've just mixed up values and indices in a few places.
You need to replace:
max = entries.get(i).getValue();
with
max = i;
This
max = entries.get(j).getValue();
with
max = j;
And
entries.set(entries.get(i).getValue(), entries.get(max));
entries.set(entries.get(max).getValue(), temp1);
with
entries.set(i, entries.get(max));
entries.set(max, temp1);
Make you sure you understand why the changes work.

Sort the array elements based on the elements frequency in java

I have written code to sort the array in java based on the frequency of the elements in it. I need better code or pseudo code (without collection framework).Please help with links or code.
public class SortByFreq1 {
public static void main(String[] args) {
int arr[] = { 2, 5, 2, 8, 5, 6, 8, 8, 0, -8 };
int nArr[] = new int[arr.length];
Map<Integer,Integer> map = new HashMap<Integer, Integer>();
Map<Integer,Integer> sortmap = new HashMap<Integer, Integer>();
ArrayList<Integer> arrList = new ArrayList<Integer>();
for (int i = 0; i < arr.length; i++) {
arrList.add(arr[i]);
}
Set<Integer> set = new HashSet<Integer>(arrList);
for (Integer i : set) {
map.put(i, Collections.frequency(arrList, i));
}
// System.out.println(map.keySet());
// sort map by value
Set<Entry<Integer,Integer>> valList=map.entrySet();
ArrayList<Entry<Integer, Integer>> tempLst = new ArrayList<Map.Entry<Integer, Integer>>(valList);
Collections.sort(tempLst, new Comparator<Entry<Integer, Integer>>() {
#Override
public int compare(Entry<Integer, Integer> o1, Entry<Integer, Integer> o2) {
return o2.getValue().compareTo(o1.getValue());
}
});
int k = 0;
for (Entry<Integer, Integer> entry : tempLst) {
int no = entry.getKey();
int noOfTimes = entry.getValue();
int i = 0;
while (i < noOfTimes) {
nArr[k++] = no;
i++;
}
}
for (int i = 0; i < nArr.length; i++)
System.out.print(nArr[i] + " ");
}
}
The logic behind it is quite similar to Counting Sort.
ATTENTION: We are NOT to modify the array passed in.
There are two different methods while having almost the same time and space complexity.
Time complexity: max(n, O(klogk));
Space complexity: O(n) - the array to be returned;
k mentioned above is the amount of distinct numbers in the array.
Built-in Collection Method
Using Stream perhaps we can make the process a little bit cleaner though OP is not asking for this:
/**
* 1. count the frequency and sort the entry based on the frequency while using LinkedHashMap to retain the order;
* 2. fill up the new array based on the frequency while traversing the LinkedHashMap;
* #param arr
* #return
*/
private static int[] sortByCounting(int[] arr) {
Map<Integer, Long> countMap = Arrays.stream(arr).boxed()
.collect(Collectors.groupingBy(Integer::intValue, Collectors.counting()))
.entrySet().stream()
.sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldV, newV) -> oldV, LinkedHashMap::new));
int[] newArr = new int[arr.length];
int i = 0;
for (Map.Entry<Integer, Long> entry : countMap.entrySet()) {
Arrays.fill(newArr, i, i += entry.getValue().intValue(), entry.getKey());
}
return newArr;
}
Custom Method
Since we cannot use built-in collection methods, meantime we have to record the count for the number.
Instinctively, we could introduce a custom pair to record the number and its related frequency (or count we could say) as our custom method.
private static int[] sortByPlainCounting(int[] arr) {
if (arr.length < 1) throw new IllegalArgumentException("Array cannot be empty");
MyPair[] pairs = prepareMyPairs(arr);
Arrays.sort(pairs, Comparator.comparing(MyPair::getCount).reversed());
int[] newArr = new int[arr.length];
int i = 0;
for (MyPair pair : pairs) {
Arrays.fill(newArr, i, i += pair.count, pair.key);
}
return newArr;
}
static class MyPair {
int key;
int count;
public MyPair(int theKey) {
this.key = theKey;
this.count = 1;
}
public void inc() {
this.count++;
}
public int getCount() {
return this.count;
}
}
static MyPair[] prepareMyPairs(int[] arr) {
Integer[] tmpArr = Arrays.stream(arr).boxed().toArray(Integer[]::new);
Arrays.sort(tmpArr, Comparator.reverseOrder());
int count = 1;
int prev = tmpArr[0];
for (int i = 1; i < tmpArr.length; i++) {
if (tmpArr[i] != prev) {
prev = tmpArr[i];
count++;
}
}
MyPair[] pairs = new MyPair[count];
int k = 0;
for (int i = 0; i < tmpArr.length; i++) {
if (pairs[k] == null) {
pairs[k] = new MyPair(tmpArr[i]);
} else {
if (pairs[k].key == tmpArr[i]) {
pairs[k].inc();
} else {
k++; i--;
}
}
}
return pairs;
}
A comparison and demonstration
Make a final comparison, we can prove that:
average time cost of custom is a little bit worse (1.4 times worse) while the worst case is far better (4 times better) than the built-in collection method;
the custom method is correct;
public static void main(String[] args) {
int N = 10_000 + new Random().nextInt(100);
Long start;
List<Long> list0 = new ArrayList<>();
List<Long> list1 = new ArrayList<>();
for (int i = 0; i < 100; ++i) {
int[] arr = RandomGenerator.generateArrays(N, N, N / 10, N / 5, false);
start = System.nanoTime();
int[] arr0 = sortByCounting(arr);
list0.add(System.nanoTime() - start);
start = System.nanoTime();
int[] arr1 = sortByPlainCounting(arr);
list1.add(System.nanoTime() - start);
System.out.println(isFrequencyEqual(arr0, arr1));
}
System.out.println("Collection time cost: " + list0.stream().collect(Collectors.summarizingLong(Long::valueOf)));
System.out.println("Custom time cost: " + list1.stream().collect(Collectors.summarizingLong(Long::valueOf)));
}
private static boolean isFrequencyEqual(int[] arr0, int[] arr1) {
Map<Integer, Long> countMap0 = getCountMap(arr0);
Map<Integer, Long> countMap1 = getCountMap(arr1);
boolean isEqual = countMap0.entrySet().size() == countMap1.entrySet().size();
if (!isEqual) return false;
isEqual = countMap0.values().containsAll(countMap1.values()) &&
countMap1.values().containsAll(countMap0.values());
if (!isEqual) return false;
List<Long> countList0 = countMap0.values().stream().collect(Collectors.toList());
List<Long> countList1 = countMap1.values().stream().collect(Collectors.toList());
for (int i = 0; i < countList0.size(); i++) {
if (countList1.get(i) != countList0.get(i)) return false;
}
return true;
}
private static Map<Integer, Long> getCountMap(int[] arr) {
return Arrays.stream(arr).boxed()
.collect(Collectors.groupingBy(Integer::intValue, Collectors.counting()))
.entrySet().stream()
.sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldV, newV) -> oldV, LinkedHashMap::new));
}
The helper util method:
public static int[] generateArrays(int minSize, int maxSize, int low, int high, boolean isUnique) {
Random random = new Random(System.currentTimeMillis());
int N = random.nextInt(maxSize - minSize + 1) + minSize;
if (isUnique) {
Set<Integer> intSet = new HashSet<>();
while (intSet.size() < N) {
intSet.add(random.nextInt(high - low) + low);
}
return intSet.stream().mapToInt(Integer::intValue).toArray();
} else {
int[] arr = new int[N];
for (int i = 0; i < N; ++i) {
arr[i] = random.nextInt(high - low) + low;
}
return arr;
}
}
And the test output:
Sorted by frequency: true
// ... another 98 same output
Sorted by frequency: true
Collection time cost: LongSummaryStatistics{count=100, sum=273531781, min=466684, average=2735317.810000, max=131741520}
Custom time cost: LongSummaryStatistics{count=100, sum=366417748, min=1733417, average=3664177.480000, max=27617114}
Can be done in O(n) using pigeonhole sort. Pseudo code:
counts = new HashMap<Item, int>(),;
foreach item in elements:
counts[item] += 1;
buckets = new List<Item>[elements.length+1];
foreach item in counts:
buckets[counts[item]].Append(item)
for i from 1 to elements.length:
bucket = buckets[i]; /* edit: looping over i instead over bucket */
for item in bucket:
/* edit: if the out has to preserve the original number of elements
such as [1,5,5,0,1,9,1] will print
9,0,5,5,1,1,1 instead of 9,0,5,1, then the next line
has to be repeated i times*/
System.out.println(item)
edit: The same can be written without collection framework, by implementing a hash table and a linked list:
class Node {
public Node next;
public int value;
};
log2count = Math.ceil(Math.log(elements.length) / Math.log(2));
hashSize = (int) Math.Round(Math.Pow(2, log2count) * 2);
/* countsQuadraticProbing[i] is 0 if the hash entry is empty,
otherwise it contains the frequency of the element in
elementsQuadraticProbing[i].
Note that quadratic probing over a hash table of size 2**k,
and probing of (0.5 i + 0.5 i**2) is guaranteed to find an empty
entry if the hash table is not full.
*/
countsQuadraticProbing = new int[hashSize];
elementsQuadraticProbing = new int[hashSize];
foreach item in elements:
for i from 0 to hashSize-1:
index = (item + (i * (i + 1) / 2)) % hashSize;
if countsQuadraticProbing[index] == 0:
countsQuadraticProbing[index] = 1;
elementsQuadraticProbing[index] = item;
break;
if elementsQuadraticProbing[index] == item:
countsQuadraticProbing[index]++;
break;
buckets = new Node[elements.length+1];
for i from 0 to hashSize-1:
count = countsQuadraticProbing[index];
if count != 0:
Node topNode = new Node();
topNode.next = buckets[count];
topNode.value = elementsQuadraticProbing[i];
buckets[count] = topNode;
/* there are O(N) buckets, total of elements in all buckets O(N),
overall complexity of the nested loop O(N)
*/
for i from 1 to elements.length:
node = buckets[i] /* edit: using i for iteration */
while node != null:
/* edit: if the out has to preserve the original number of elements
such as [1,5,5,0,1,9,1] will print
9,0,5,5,1,1,1 instead of 9,0,5,1, then the next line
has to be repeated i times*/
System.out.println(node.value);
node = node.next;
I'm just curious why couldn't you use the good old bubble sort in the case and just customize a bit the Bubble In worst case scenario the time complexity is going to be O(n*n) and space complexity will be O(3n) :)
Pure arrays implementation is going to be something like:
private static void bubbleSortByOccurrences(int[] arr) {
int[][] counter = new int[2][arr.length];
int counterIndex = -1;
for (int value : arr) {
int idx = 0;
for (; idx <= counterIndex; idx++) {
if (counter[0][idx] == value) {
counter[1][idx]++;
while (idx > 0 && counter[1][idx] > counter[1][idx-1]) {
int temp = counter[1][idx];
counter[0][idx] = counter[0][idx-1];
counter[1][idx] = counter[1][idx-1];
counter[0][idx-1] = value;
counter[1][idx-1] = temp;
idx--;
}
break;
}
}
if (idx > counterIndex) {
counter[0][idx] = value;
counter[1][idx]++;
counterIndex = idx;
}
}
fillArrayBackwards(arr, counter, counterIndex);
}
private static void fillArrayBackwards(int[] buf, int[][] counter, int counterIndex) {
for (int i = counterIndex, j = buf.length - 1; i >=0; i--) {
for (int k = 0; k < counter[1][i]; k++) {
buf[j--] = counter[0][i];
}
}
}
And the same algorithm implemented by using a Bubble class will look something like:
private static void bubbleSortByOccurrences(int[] arr) {
Bubble head = null;
for (int value : arr) {
if (head == null) {
head = new Bubble(value);
} else {
Bubble currentHead = null;
Bubble current = head;
for (; current != null && !(current.getValue() == value); current = current.getTail()) {
currentHead = current;
}
if (current == null) {
current = new Bubble(value);
current.setTail(head);
head = current;
} else {
current.incrementOccurrences();
while (current.getTail() != null && current.getOccurrences() > current.getTail().getOccurrences()) {
Bubble currentTail = current.getTail();
current.setTail(currentTail.getTail());
currentTail.setTail(current);
if (currentHead != null) {
currentHead.setTail(currentTail);
currentHead = currentTail;
} else {
head = currentTail;
}
}
}
}
}
fillArrayBackwards(arr, head);
}
private static void fillArrayBackwards(int[] buf, Bubble head) {
int i = buf.length - 1;
for (Bubble current = head; current != null; current = current.getTail()) {
for (int j = 0; j < current.getOccurrences(); j++) {
buf[i--] = current.getValue();
}
}
}
Where the custom defined bubble is as follows:
class Bubble {
private int value;
private int occurrences;
private Bubble tail;
public Bubble(int value) {
this.value = value;
this.occurrences = 1;
}
public int getValue() {
return value;
}
public int getOccurrences() {
return occurrences;
}
public void incrementOccurrences() {
this.occurrences++;
}
public Bubble getTail() {
return tail;
}
public void setTail(Bubble tail) {
this.tail = tail;
}
}
your solution is better but since am not using any collections it is gonna be huge.
1.sort the list
2. get the frequency of every element
3. create a new arraylist/ array and store the elements that have higher frequency to lower frequency.
sort the list using any sort algorithm
get the frequency
class CountFrequencies
{
// Function to find counts of all elements present in
// arr[0..n-1]. The array elements must be range from
// 1 to n
void findCounts(int arr[], int n)
{
// Traverse all array elements
int i = 0;
while (i < n)
{
// If this element is already processed,
// then nothing to do
if (arr[i] <= 0)
{
i++;
continue;
}
// Find index corresponding to this element
// For example, index for 5 is 4
int elementIndex = arr[i] - 1;
// If the elementIndex has an element that is not
// processed yet, then first store that element
// to arr[i] so that we don't loose anything.
if (arr[elementIndex] > 0)
{
arr[i] = arr[elementIndex];
// After storing arr[elementIndex], change it
// to store initial count of 'arr[i]'
arr[elementIndex] = -1;
}
else
{
// If this is NOT first occurrence of arr[i],
// then increment its count.
arr[elementIndex]--;
// And initialize arr[i] as 0 means the element
// 'i+1' is not seen so far
arr[i] = 0;
i++;
}
}
System.out.println("Below are counts of all elements");
for (int j = 0; j < n; j++)
System.out.println(j+1 + "->" + Math.abs(arr[j]));
}
above code should give you an output:
1 -> 3
2 -> 0
3 -> 2
4 -> 0
5 -> 2
6 -> 0
7 -> 2
8 -> 0
9 -> 2
10 -> 0
11 -> 0
Now you can easily use the array that stored the frequency of every element to create a new array that contains the most frequent elements in the array
Note that the list is sorted so that arr[0] is the frequency of 1 arr[1] is the frequency of 2 and so on. Again The code is not efficient as yours it is better to use the collection framework.
or if you are familiar use binary trees you can add the element into the tree and use inorder traversal !
Hope you find my answer helpful

Having a casting issue with traveling salesperson using a greedy algorithm

I figure I have the general idea down for how to solve the algorithm but the implementation seems to elude me. What I have thus far is this:
public class GreedySalesman {
public static int[] greedySalesmanSolution(int[][] distances) {
List cityList = new ArrayList();
for(int[] array: distances) {
cityList.add(Arrays.asList(array));
}
List<Integer> initialResult = new ArrayList();
initialResult.add(0);
List<Integer> finalResult = findMinDistance(cityList, cityList, initialResult, 0);
/*int finalResultArray = new int[finalResult.size()+1];
int i = 0;
while (!(finalResult.isEmpty)) {
finalResultArray[i] = finalResult.poll();
i++;
}
return finalResultArray;
*/
return null;
}
public static List<Integer> findMinDistance(List<List<Integer>> initialCityInput, List<List<Integer>> cityInput, List<Integer> distanceResult, int index) {
if(cityInput.isEmpty()) {
distanceResult.add(0);
return distanceResult;
}
int min = Collections.min(initialCityInput.get(index));
List<Integer> city = initialCityInput.get(index);
index = city.indexOf(min);
distanceResult.add(index);
cityInput.remove(city);
return findMinDistance(initialCityInput,cityInput,distanceResult,index);
}
}
That is, the algorithm will take an two dimensional array of ints as an input, then make a List cityList referring to distances, then pass it into findMinDistance. The commented out part is where the result from findMinDistance will be converted into an array of ints and returned as finalResultArray but that part is not important yet.
findMinDistance will take in a two dimensional list of Integers twice, a List of Integers that will become the result and an int representing an index.
The function will return the distanceResult when cityInput has been emptied. Otherwise it will start with the first city based on the index, get the minimum distance from that List and its index and add the index to the distanceResult.
Once that has been done, the city will be removed from the cityInput and the program will go into recursion until cityInput has been emptied.
The issue I am getting currently is
I cannot be cast to java.lang.Integer
at
int min = Collections.min(initialCityInput.get(index));
And in main upon trying to run the program with some test data.
Any help will be appreciated.
======
Edit:
I made some changes to my code
public class GreedyTSP {
public int[] greedySalesmanSolution(int[][] distances) {
List<List<Integer>> cityList = new ArrayList();
List<List<Integer>> initialCityList = new ArrayList();
int iLength = distances.length;
for (int i = 0; i < iLength; ++i) {
int jLength = distances[0].length;
cityList.add(new ArrayList(jLength));
initialCityList.add(new ArrayList(jLength));
for (int j = 0; j < jLength; ++j) {
cityList.get(i).add(distances[i][j]);
initialCityList.get(i).add(distances[i][j]);
}
}
List<Integer> initialResult = new ArrayList();
initialResult.add(0);
List<Integer> finalResult = findMinDistance(initialCityList, cityList, initialResult, 0);
int[] finalResultArray = new int[finalResult.size()];
Iterator<Integer> iterator = finalResult.iterator();
for (int i = 0; i < finalResultArray.length; i++){
finalResultArray[i] = iterator.next().intValue();
}
return finalResultArray;
}
public List<Integer> findMinDistance(List<List<Integer>> initialCityInput, List<List<Integer>> cityInput, List<Integer> distanceResult, int initialIndex) {
if(cityInput.isEmpty()) {
distanceResult.add(0);
return distanceResult;
}
List<Integer> city = initialCityInput.get(initialIndex);
Integer min = findMin(city, distanceResult, initialIndex);
int resultIndex = city.indexOf(min);
distanceResult.add(resultIndex);
cityInput.remove(city);
return findMinDistance(initialCityInput,cityInput,distanceResult,resultIndex);
}
public Integer findMin(List<Integer> city, List<Integer> distanceResult, int inputIndex) {
Integer min = Integer.MAX_VALUE;
for(int i = 0; i < city.size();i++) {
if (city.get(i) > inputIndex && city.get(i) < min) min = city.get(i);
}
int resultIndex = city.indexOf(min);
if(distanceResult.contains(resultIndex)) {
return findMin(city, distanceResult, inputIndex);
}
return min;
}
}
Im not having any cast errors at the moment but it seems that the parts of my program dealing with recursion are causing StackOverflowError-s. I've been messing with this thing for literally 16 hours now and I'm all out of ideas as to why. Any ideas?
The problem with your casting is the following
List<List<Integer>> initialCityInput is a List containing Lists with integers.
Therefore initalCityInput.get(index) returns a List not an Int, which cannot be cast to int.
Well, I looked around a bit and I was basically overcomplicating the task through using multidimensional arraylists. I changed the code quite a bit:
public class GreedyTSP {
public static int[] greedySolution(int[][] adjacencyMatrix) {
List<Integer> visitedCities = new ArrayList<>();
int min = Integer.MAX_VALUE;
int startLocation = 0;
int tempStartLocation = 0;
int[] resultArray = new int[adjacencyMatrix.length+1];
visitedCities.add(0);
while(visitedCities.size() < adjacencyMatrix.length ){
for(int i = 0; i < adjacencyMatrix.length; i++){
if(!visitedCities.contains(i) && adjacencyMatrix[startLocation][i] < min){
min = adjacencyMatrix[startLocation][i];
tempStartLocation = i;
}
}
startLocation = tempStartLocation;
visitedCities.add(tempStartLocation);
min = Integer.MAX_VALUE;
}
visitedCities.add(0);
for(int i = 0; i < resultArray.length; i++){
int temp = visitedCities.get(i);
resultArray[i] = temp;
}
return resultArray;
}
}
This will solve the task using a greedy algorithm

Iterating over an ArrayList adding values

Is it possible to iterate over a ArrayList adding not all instances but every 12? There are many threads on using addAll to add all instances but not sections.
I currently have an ArrayList containing hundreds of float values:
Snippet:
120.5, 22.2, 76.2, 64.5, 38.3, 27.1, 149.4, 62.3, 127.9, 79.1, 83.4, 68.3, 61.0, 83.4, 5.4, 83.8, 78.3, 111.8, 104.1, 145.2, 94.3, 20.0, 104.7, 35.9, 68.6, 10.1, 41.1, 82.2, 170.7, 17.2, 122.1, 61.0, 46.3, 101.1, 59.0, 30.0, ...
What I want to do is sum the first 12 instances and put this total in a new ArrayList, sum the next 12 instances, store this into the newly created ArrayList and so on. There are exactly 996 instances so i should have 83 new values in this new ArrayList (996/12=83).
Can this be done? If so how? Here is where I have got to...
// ArrayList that contains the float values shown above
public MonthData depthValues() {
ArrayList<Float> rValue = new ArrayList<>();
for (int i = 0; i<months.size(); i++)
{
rValue.add(months.get(i).getDepthMM());
}
System.out.println(rValue);
System.out.println(rValue.size());
return null;
}
//New arrayList im trying to make
//probably done this wrong, help needed here
public MonthData depthTotals() {
ArrayList<Float> depthAdd = new ArrayList<Float>();
int t = 12;
for(int i = 0; i<rValue.size(); ++i)
{
??????????????????
}
}
Any help will be greatly appreciated I cant seem to find anything on this anywhere as I think the sum of all instances is such a popular topic. Its probably a case of iterating properly. In regards to the summing I would have use accumulate in c++, but do not know the equivalent of this in java (if there is one). Thank you for any advice/assistance in advance!
MORE CODE:
public class WeatherStation {
private ArrayList<MonthData> months;
private ArrayList<MonthData> rValue;
private ArrayList<MonthData> depthAdd;
MonthData is a model for data being read to this class it consists on a lot of getters....
public class MonthData {
int y;
int m;
float h;
...
public MonthData(String data) throws Exception {
...
this.parseData(data);
}
void parseData(String csvData) {
String[] parseResult = csvData.trim().split("\\s+");
this.setYear(parseResult[0]);
this.setMonth(parseResult[1]);
...
public String toString() {
return "y =" + year + ", m =" + month + ",...
}
public int getY() {
return y;
}
// followed by lots of getters for: m, h, c, f, r, s, ...
public MonthData depthValues() {
ArrayList<Float> rValue = new ArrayList<>();
for (int i = 0; i<months.size(); i++)
{
rValue.add(months.get(i).getDepthMM());
}
System.out.println(rValue);
System.out.println(rValue.size());
return null;
}
Code recommended:
public MonthData depthTotals() {
ArrayList<Float> depthAdd = new ArrayList<>();
Iterator<Float> it = rValue.iterator();
final int MAX = 12;
while (it.hasNext()){
float sum = 0f;
int counter = 1;
//iterating 12 times
//still check if there is an element in list
while (counter < MAX && it.hasNext()){
sum += it.next();
counter++;
}
depthAdd.add(sum);}
}
ISSUE: Iterator<Float> it = rValue.iterator();
Type mismatch: cannot convert from Iterator<MonthData> to Iterator<Float>
The best way to do this is using Iterator and a counter of 12 by using a while. Here's an example:
List<Float> yourList = ...;
// fill yourList
List<Float> results = new ArrayList<>();
Iterator<Float> it = yourList.iterator();
final int MAX = 12;
while (it.hasNext()) {
float sum = 0f;
int counter = 1;
//iterating 12 times
//still, check if there's an element in your list
while (counter <= MAX && it.hasNext()) {
sum += it.next();
counter++;
}
result.add(sum);
}
I would recommend you use double or Double instead of float as it has around half a trillion times the accuracy.
You can sum every block of 12 like this
public static List<Double> sumBlocks(List<Double> list, int blockSize) {
List<Double> ret = new ArrayList<>();
for(int i = 0; i < list.size(); i += blockSize) {
double sum = 0;
for(int j = 0, len = Math.min(list.size() - i, blockSize); j < len; j++)
sum += list.get(i + j);
ret.add(sum);
}
return ret;
}
and call
List<Double> sums = sumBlocks(list, 12);
Just to demonstrate yet another way to accomplish this:
public static List<Double> sumBlocks(List<Double> list, int blockSize) {
List<Double> result = new ArrayList<>();
double sum = 0d;
for (int i = 0; i < list.size(); i++) {
if (i > 0 && i % blockSize == 0) {
result.add(sum);
sum = 0d;
}
sum += list.get(i);
}
result.add(sum);
return result;
}
Lista<Double> list = // original list
List<Double> ret = new ArrayList<>();
int counter = 0;
double sum = 0;
for (Double f : list) {
if (counter == 12) {
sum = 0;
counter = 0;
ret.add(sum);
}
sum += f;
counter++;
}
// if list is not a multiple of 12
if (list.size() % 12 != 0) {
ret.add(sum);
}
return ret;
try this:
public float total;
for(int i; i < rValue.Size(); i ++)
{
total += rValue[i];
if(i%12=0)
{
add total to new ArrayList
total = 0;
}
}
Arraylist objects inherit the sublist(start, end) method from the List class. You can use myList.sublist(i, j) to access the sublist and get your sum. From there, it should be just simple arithmetic to get your iteration. Inside your for-loop, it should be: myList.sublist(i*12, i*12 + 12).
//Input list
ArrayList<Float> inputList = new ArrayList<Float>();
ArrayList<Float> result = new ArrayList<Float>();
int groupSize = 12;
int offset=0;
while(offset < inputList.size()) {
int toIndex = (inputList.size()-offset)>=groupSize? offset+groupSize : inputList.size();
result.add( listSum(inputList.subList(offset, toIndex)) );
offset += groupSize;
}
Helper method to add items in a list
static float listSum(List<Float> ar) {
float accumulator = 0f;
for(float item:ar) {
accumulator += item;
}
return accumulator;
}

Categories