Comparing elements in a list and swapping them. Java - java

Hi I have been working on a solution for days, and I've been trying to figure it out on my own but I just can't.
I have an ArrayList and I want to swap the elements in it. But I want to compare the list in halves. So say if the list had 8 elements in it, I would want to compare the first element in the first half of the list with the first element in the second half of the list.
So list[0] with list[4] and if 4 is bigger than 0, i want to swap them, then i want to increment 0 and by 1, and half the list by one, until i = 4.
I have to run it from the command line.
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Collections;
public class TennisTournament {
public static void main (String [] args) {
Scanner input = new Scanner(System.in);
ArrayList <Integer> nums = new ArrayList<Integer>();
while (input.hasNextInt()) {
nums.add(input.nextInt());
}
tournament(nums); }
public static void tournament(ArrayList <Integer> list) {
int midPoint = list.size()/2; // returns the index number of half of the lists size
for (int i = 0; i < midPoint; i++) { // while is bigger than mid point, increment by one
if (list.get(i) < list.get(midPoint)) {
Collections.swap(list, i, midPoint);
System.out.print(list);
}
}
System.out.println(list); }
}
This is what I have so far, but when I run it from the command line, it just returns an ordinary list, and I'm completely stumped. I would much rather use a loop than the collections method as it is not a style of programming i am particular familiar with.

Look at midPoint - it never changes inside the loop. You're continually exchanging the i-th element (provided that the "if" condition is true) with the midPoint. No element after midPoint is ever touched.

Related

Removing every other element in an array list

for(int i = 0; i < points.size(); i = i+lines) {
points.remove(i);
}
The idea here is that a user can either remove every other space or every third space or every fourth space .. And so forth, of an array list by entering an int "line" that will skip the spaces. However, I realize the list gets smaller each time messing with the skip value. How do I account for this? I'm using the ArrayList library from java so don't have the option of just adding a method in the array list class. Any help would be greatly appreciated.
I've perfomed a benchmark of all the answers proposed to this question so far.
For an ArrayList with ~100K elements (each a string), the results are as follows:
removeUsingRemoveAll took 15018 milliseconds (sleepToken)
removeUsingIter took 216 milliseconds (Arvind Kumar Avinash)
removeFromEnd took 94 milliseconds (WJS)
Removing an element from an ArrayList is an Θ(n) operation, as it has to shift all remaining elements in the array to the left (i.e. it's slow!). WJS's suggestion of removing elements from the end of the list first, appears to be the fastest (inplace) method proposed so far.
However, for this problem, I'd highly suggest considering alternative data structures such as a LinkedList, which is designed to make removing (or adding) elements in the middle of the list fast. Another alternative, if you have sufficient memory, is to build up the results in a separate list rather than trying to modify the list inplace:
removeUsingIterLinked took 12 milliseconds
removeUsingSecondList took 3 milliseconds (sleepToken with WJS's comment)
Use an Iterator with a counter e.g. the following code will remove every other (i.e. every 2nd) element (starting with index, 0):
Iterator<Point> itr = points.iterator();
int i = 0;
while(itr.hasNext()) {
itr.next();
if(i % 2 == 0) {
itr.remove();
}
i++;
}
Here, I've used i as a counter.
Similarly, you can use the condition, i % 3 == 0 to remove every 3rd element (starting with index, 0).
Here is a different approach. Simply start from the end and remove in reverse. That way you won't mess up the index synchronization. To guarantee that removal starts with the second item from the front, ensure you start with the last odd index to begin with. That would be list.size()&~1 - 1. If size is 10, you will start with 9. If size is 11 you will start with 9
List<Integer> list = IntStream.rangeClosed(1,11)
.boxed().collect(Collectors.toList());
for(int i = (list.size()&~1)-1; i>=0; i-=2) {
list.remove(i);
}
System.out.println(list);
Prints
[1, 3, 5, 7, 9, 11]
You could add them to a new ArrayList and then remove all elements after iterating.
You could set count to remove every countth element.
import java.util.ArrayList;
public class Test {
static ArrayList<String> test = new ArrayList<String>();
public static void main(String[] args) {
test.add("a");
test.add("b");
test.add("c");
test.add("d");
test.add("e");
ArrayList<String> toRemove = new ArrayList<String>();
int count = 2;
for (int i = 0; i < test.size(); i++) {
if (i % count == 0) {
toRemove.add(test.get(i));
}
}
test.removeAll(toRemove);
System.out.print(test);
}
}

Store a numbers in stack and print it in queue

if i store a numbers in stack , and i want to print it in queue , should i store the same numbers in queue again to print it , or there is another way to do it ?
import java.util.Stack;
import java.util.PriorityQueue;
import java.util.Scanner ;
public class Qa {
public static void main(String[] args) {
Scanner input = new Scanner (System.in);
Stack<Integer> A =new Stack<Integer>();
System.out.println(" the numbers should be less than 99 ");
int x = input.nextInt() ;
while(x> 0 && x < 99){
A.push(x);
}
PriorityQueue<String> B =new PriorityQueue<String>();
}
Queue is basically FIFO. First store the elements in a Stack. Pop the elements and store it again in another Stack. Now pop the elements you will get it as FIFO(Queue).
You can initialize a List with the contents of the stack and then print from the List? You can print from last element in List till first
i don't know what you specific want to do, but if you have the numbers stored, you don't need to re-store again. You can just reed them in from the [first-->last] or [last-->first].
An example with code is here:
CodeExample
with that you save memory and time. :)
Is suppose that you utilizes the stack structure for some reason, but the results could be the same, storing data in a simple list, and then depending in what you wanna do, uses that list. You could save space and time, because doesn't be necessary duplicate data or make unnecessary loops on complex data structures.
Hope this helps.
java.util.Stack it is an ordered Iterable like a List. you can get the elements in order of insertion by iterating over the stack with a for loop (or .forEach in Java 8).
I'm pasting the example code and output below:
public class MyApp {
public static void main(String[] args) {
Stack<Integer> myInts = new Stack<>();
for (int i = 0; i < 5; i++) {
myInts.push(i);
}
System.out.println("ITERATING:");
myInts.forEach(System.out::println);
System.out.println("\nPOPPING:");
while(!myInts.isEmpty()) {
System.out.println(myInts.pop());
}
}
}
The output is:
ITERATING:
0
1
2
3
4
POPPING:
4
3
2
1
0
You see that if you iterate over the Stack it returns the numbers in order of insertion. If your intent is just print the contents of the stack this approach has the additional benefit of not having to mutate the stack by calling pop().

How to divide a set of numbers into two sets such that the difference of their sum is minimum

How to write a Java Program to divide a set of numbers into two sets such that the difference of the sum of their individual numbers, is minimum.
For example, I have an array containing integers- [5,4,8,2]. I can divide it into two arrays- [8,2] and [5,4]. Assuming that the given set of numbers, can have a unique solution like in above example, how to write a Java program to achieve the solution. It would be fine even if I am able to find out that minimum possible difference.
Let's say my method receives an array as parameter. That method has to first divide the array received into two arrays, and then add the integers contained in them. Thereafter, it has to return the difference between them, such that the difference is minimum possible.
P.S.- I have had a look around here, but couldn't find any specific solution to this. Most probable solution seemed to be given here- divide an array into two sets with minimal difference . But I couldn't gather from that thread how can I write a Java program to get a definite solution to the problem.
EDIT:
After looking at the comment of #Alexandru Severin, I tried a java program. It works for one set of numbers [1,3,5,9], but doesn't work for another set [4,3,5,9, 11]. Below is the program. Please suggest changes:-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class FindMinimumDifference {
public static void main(String[] args) {
int[] arr= new int[]{4,3,5,9, 11};
FindMinimumDifference obj= new FindMinimumDifference();
obj.returnMinDiff(arr);
}
private int returnMinDiff(int[] array){
int diff=-1;
Arrays.sort(array);
List<Integer> list1= new ArrayList<>();
List<Integer> list2= new ArrayList<>();
int sumOfList1=0;
int sumOfList2=0;
for(int a:array){
for(Integer i:list1){
sumOfList1+=i;
}
for(Integer i:list2){
sumOfList2+=i;
}
if(sumOfList1<=sumOfList2){
list1.add(a);
}else{
list2.add(a);
}
}
List<Integer> list3=new ArrayList<>(list1);
List<Integer> list4= new ArrayList<>(list2);
Map<Integer, List<Integer>> mapOfProbables= new HashMap<Integer, List<Integer>>();
int probableValueCount=0;
for(int i=0; i<list1.size();i++){
for(int j=0; j<list2.size();j++){
if(abs(list1.get(i)-list2.get(j))<
abs(getSumOfEntries(list1)-getSumOfEntries(list2))){
List<Integer> list= new ArrayList<>();
list.add(list1.get(i));
list.add(list2.get(j));
mapOfProbables.put(probableValueCount++, list);
}
}
}
int minimumDiff=abs(getSumOfEntries(list1)-getSumOfEntries(list2));
List resultList= new ArrayList<>();
for(List probableList:mapOfProbables.values()){
list3.remove(probableList.get(0));
list4.remove(probableList.get(1));
list3.add((Integer)probableList.get(1));
list4.add((Integer)probableList.get(0));
if(minimumDiff>abs(getSumOfEntries(list3)-getSumOfEntries(list4))){
// valid exchange
minimumDiff=abs(getSumOfEntries(list3)-getSumOfEntries(list4));
resultList=probableList;
}
}
System.out.println(minimumDiff);
if(resultList.size()>0){
list1.remove(resultList.get(0));
list2.remove(resultList.get(1));
list1.add((Integer)resultList.get(1));
list2.add((Integer)resultList.get(0));
}
System.out.println(list1+""+list2); // the two resulting set of
// numbers with modified data giving expected result
return minimumDiff;
}
private static int getSumOfEntries(List<Integer> list){
int sum=0;
for(Integer i:list){
sum+=i;
}
return sum;
}
private static int abs(int i){
if(i<=0)
i=-i;
return i;
}
}
First of all, sorting the array then putting first member in group and second in another wound never work, and here is why:
Given the input[1,2,3,100].
The result would be: [1,3] and [2,100], clearly wrong.
The correct answer should be: [1,2,3] and [100]
You can find many optimization algorithms on google for this problem, but since I assume you're a beginner, I'll try to give you a simple algorithm that you can implement:
sort the array
iterate from highest to lowest value
for each iteration, calculate the sum of each group, then add the element to the group with minimum sum
At the end of the loop you should have two fairly balanced arrays. Example:
Array: [1,5,5,6,7,10,20]
i1: `[20] []`
i2: `[20] [10]`
i3: `[20] [10,7]`
i4: `[20] [20,7,6]`
i5: `[20,5] [10,7,6]`
i6: `[20,5] [10,7,6,5]`
i7: `[20,5,1] [10,7,6,5]`
Where the sums are 26 and 28. As you can see we can further optimize the solution, if we exchange 5 and 6 resulting in [20,6,1] and [20,7,5,5] the sums are equal.
For this step you can:
find all groups of elements (x,y) where x is in group1, y is in group2, and |x-y| < |sum(group1) - sum(group2)|
loop all groups and try exchanging x with y until you get a minimum difference
after each exchange check if the minimum value in the group with the highest sum is higher then the difference of the groups, if so, transfer it to the other group
This algorithm will always return the best solution, and is a whole lot better then a greedy approach. However it is not optimal in terms of complexity, speed and memory. If one needs it for very large arrays and the resources are limited, the most optimal algorithm may differ depending on the speed/memory ration and the accepted error percentage.
This is a variation on the Partition Problem https://en.wikipedia.org/wiki/Partition_problem
If you want the optimal solution you have to test every possible combination of output sets. That may be feasible for small sets but is infeasible for large inputs.
One good approximation is the greedy algorithm I present below.
This heuristic works well in practice when the numbers in the set are
of about the same size as its cardinality or less, but it is not
guaranteed to produce the best possible partition.
First you need to put your input in a sortable collection such as a List.
1) Sort the input collection.
2) Create 2 result sets.
3) Iterate over the sorted input. If the index is even put the item in result1 else put the item in result2.
List<Integer> input = new ArrayList<Integer>();
Collections.sort(input);
Set<Integer> result1 = new HashSet<Integer>();
Set<Integer> result2 = new HashSet<Integer>();
for (int i = 0; i < input.size(); i++) {
if (i % 2 == 0) {// if i is even
result1.add(input.get(i));
} else {
result2.add(input.get(i));
}
}
I seem to have got the perfect solution for this. Below Java program works perfectly. Only assumption is that, the given problem has unique solution (just one solution). This assumption implies- only non-zero number. I am putting the program below. I request everyone to tell if the program could fail for certain scenario, or if it could be improved/optimized in some way. Credits to Mr Alexandru Severin's algorithm posted as one of the answers in this thread.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class FindMinimumDifference {
static List<Integer> list1= new ArrayList<>();
static List<Integer> list2= new ArrayList<>();
public static void main(String[] args) {
int[] arr= new int[]{3,-2,9,7};
// tested for these sample data:- [1,5,9,3] ; [4,3,5,9,11] ;
//[7,5,11,2,13,15,14] ; [3,2,1,7,9,11,13] ;
//[3,1,0,5,6,9] ; [6,8,10,2,4,0] ; [3,1,5,7,0] ; [4,-1,5,-3,7] ; [3,-2,9,7]
System.out.println("the minimum possible difference is: "+returnMinDiff(arr));
System.out.println("the two resulting set of nos. are: "+list1+" and "+list2);
}
private static int returnMinDiff(int[] array){
int diff=-1;
Arrays.sort(array);
for(int a:array){
int sumOfList1=0;
int sumOfList2=0;
for(Integer i:list1){
sumOfList1+=i;
}
for(Integer i:list2){
sumOfList2+=i;
}
if(sumOfList1<=sumOfList2){
list1.add(a);
}else{
list2.add(a);
}
}
List<Integer> list3=new ArrayList<>(list1);
List<Integer> list4= new ArrayList<>(list2);
if(list3.size()!=list4.size()){ // both list should contain equal no. of entries.
//If not, add 0 to the list having lesser no. of entries
if(list3.size()<list4.size()){
list3.add(0);
}else{
list4.add(0);
}
}
Map<Integer, List<Integer>> mapOfProbables= new HashMap<Integer, List<Integer>>();
int probableValueCount=0;
for(int i=0; i<list3.size();i++){
for(int j=0; j<list4.size();j++){
if(abs(list3.get(i)-list4.get(j))
<abs(getSumOfEntries(list3)-getSumOfEntries(list4))){
List<Integer> list= new ArrayList<>();
list.add(list3.get(i));
list.add(list4.get(j));
mapOfProbables.put(probableValueCount++, list);
}
}
}
int minimumDiff=abs(getSumOfEntries(list1)-getSumOfEntries(list2));
List resultList= new ArrayList<>();
for(List probableList:mapOfProbables.values()){
list3=new ArrayList<>(list1);
list4= new ArrayList<>(list2);
list3.remove(probableList.get(0));
list4.remove(probableList.get(1));
list3.add((Integer)probableList.get(1));
list4.add((Integer)probableList.get(0));
if(minimumDiff>abs(getSumOfEntries(list3)-getSumOfEntries(list4))){ // valid exchange
minimumDiff=abs(getSumOfEntries(list3)-getSumOfEntries(list4));
resultList=probableList;
}
}
if(resultList.size()>0){ // forming the two set of nos. whose difference of sum comes out to be minimum
list1.remove(resultList.get(0));
list2.remove(resultList.get(1));
if(!resultList.get(1).equals(0) ) // (resultList.get(1).equals(0) && !list1.contains(0))
list1.add((Integer)resultList.get(1));
if(!resultList.get(0).equals(0) || (resultList.get(0).equals(0) && list2.contains(0)))
list2.add((Integer)resultList.get(0));
}
return minimumDiff; // returning the minimum possible difference
}
private static int getSumOfEntries(List<Integer> list){
int sum=0;
for(Integer i:list){
sum+=i;
}
return sum;
}
private static int abs(int i){
if(i<=0)
i=-i;
return i;
}
}
For this question, assume that we can divide the array into two subarrays such that their sum is equal. (Even thought they are not equal , it will work)
So if the sum of elements in array is S. Your goal is to find a subset with sum S/2. You can write a recursive function for this.
int difference = Integer.MAX_VALUE;
public void recursiveSum(int[] array, int presentSum, int index,Set<Integer> presentSet){
if(index == array.length){
if(Math.abs(presentSum - (S/2)) < difference)){
difference = Math.abs(presentSum - (S/2);
// presentSet is your answer
return;
}
}
recursiveSum(array,presentSum,index+1,presentSet); // don't consider the present element in the final solution
presentSet.add(array[index]);
recursiveSum(array,presentSum + array[index],index+1,presentSet); //consider the present element in the final solution
}
You can also write an equivalent O(N^2) dynamic programming code for this.
I was just demonstrating the idea.
So when you find this set with sum S/2, automatically you have divided the array in to two parts with same sum (S/2 here).
It seems that you are more interested in the algorithm than the code. So, here is my psuedocode:-
int A[];//This contains your elements in sorted (descending) order
int a1[],a2[];//The two sub-arrays
int sum1=0,sum2=0;//These store the sum of the elements of the 2 subarrays respectively
for(i=0;i<A.length;i++)
{
//Calculate the absolute difference of the sums for each element and then add accordingly and thereafter update the sum
if(abs(sum1+A[i]-sum2)<=abs(sum2+A[i]-sum1))
{a1.add(A[i]);
sum1+=A[i];}
else
{a2.add(A[i]);
sum2+=A[i];}
}
This will work for all integers, positive or negative.

Binary search algorithm does not work properly - Java

I want to make my own binary search algorithm to search ArrayList of 1 000 000 elements. I decided to do the search with do-while loop. I am aware I could use while() loop. But when I run it, it takes much time to find the number. I guess something is wrong with setting the value of first and last element of ArrayList. My code is
import java.util.*;
public class BinSearchAlg {
public static void main(String[]args){
int first;
int last;
int median;//middle element of arraylist
Long element;//element with median index
Scanner scan = new Scanner(System.in);
ArrayList<Long>list = new ArrayList();
for(long l=0;l<1000000;l++){
list.add(l);//list is sorted
}
first = 0;
last = list.size();
median = (last-first)/2;
element = list.get(median);
System.out.println("Choose the number: ");
long l = scan.nextLong();
do{
if(element<l){
first = median;
median=(last-first)/2;
element = list.get(median);
}else{ //if(element>l){
last = median;
median = (last-first)/2;
element = list.get(median);
}
}while(element!=l);
}
}
Thanks for you help.
The median calculation is problematic:
median=(last-first)/2;
You should rather do:
median=(last+first)/2;
In the current code you have, when you are searching in the range [10..16], your code will try to compare the goal with the median of list.get(3).
There could be another bug, but for now I'll leave you with this. Hint: try [0, 1], which should expose the bug in the code.
As Ziyao Wei answered, you'll need to fix the median. In addition, you'll probably need a different loop exit condition - right now you've got an infinite loop if l isn't in the list. Also, your if-else needs to be an if-elseif-else - at present if l == element then the loop will actually treat this as element > l and continue looping.
You can directly use Collection class's binary search method present java.util package :-
Collections.binarySearch(myList,key.get(i),new MyTransferObjectClass());
and
public class MyTransferObjectClass implements Comparator<MyTransferObjectClass>{
#Override
public int compare(MyTransferObjectClass o1, MyTransferObjectClass o2) {
//your logic for comparison
}
}
why to add redundant code when you can use available APIs.

ArrayList of integer arrays

I'm trying to write a simple game where an enemy chases the player on a grid. I'm using the simple algorithm for pathfinding from the Wikipedia page on pathfinding. This involves creating two lists with each list item containing 3 integers. Here's test code I'm trying out to build and display such a list.
When I run the following code, it prints out the same numbers for each array in the ArrayList. Why does it do this?
public class ListTest {
public static void main(String[] args) {
ArrayList<Integer[]> list = new ArrayList<Integer[]>();
Integer[] point = new Integer[3];
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 3; j++) {
point[j] = (int)(Math.random() * 10);
}
//Doesn't this line add filled Integer[] point to the
//end of ArrayList list?
list.add(point);
//Added this line to confirm that Integer[] point is actually
//being filled with 3 random ints.
System.out.println(point[0] + "," + point[1] + "," + point[2]);
}
System.out.println();
//My current understanding is that this section should step through
//ArrayList list and retrieve each Integer[] point added above. It runs, but only
//the values of the last Integer[] point from above are displayed 10 times.
Iterator it = list.iterator();
while (it.hasNext()) {
point = (Integer[])it.next();
for (int i = 0; i < 3; i++) {
System.out.print(point[i] + ",");
}
System.out.println();
}
}
}
First of all, several of the other answers are misleading and/or incorrect. Note that an array is an object. So you can use them as elements in a list, no matter whether the arrays themselves contain primitive types or object references.
Next, declaring a variable as List<int[]> list is preferred over declaring it as ArrayList<int[]>. This allows you to easily change the List to a LinkedList or some other implementation without breaking the rest of your code because it is guaranteed to use only methods available in the List interface. For more information, you should research "programming to the interface."
Now to answer your real question, which was only added as a comment. Let's look at a few lines of your code:
Integer[] point = new Integer[3];
This line creates an array of Integers, obviously.
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 3; j++) {
point[j] = (int)(Math.random() * 10);
}
//Doesn't this line add filled Integer[] point to the
//end of ArrayList list?
list.add(point);
//...
}
Here you assign values to the elements of the array and then add a reference to the array to your List. Each time the loop iterates, you assign new values to the same array and add another reference to the same array to the List. This means that the List has 10 references to the same array which has been repeatedly written over.
Iterator it = list.iterator();
while (it.hasNext()) {
point = (Integer[])it.next();
for (int i = 0; i < 3; i++) {
System.out.print(point[i] + ",");
}
System.out.println();
}
}
Now this loop prints out the same array 10 times. The values in the array are the last ones set at the end of the previous loop.
To fix the problem, you simply need to be sure to create 10 different arrays.
One last issue: If you declare it as Iterator<Integer[]> it (or Iterator<int[]> it), you do not need to cast the return value of it.next(). In fact this is preferred because it is type-safe.
Finally, I want to ask what the ints in each array represent? You might want to revisit your program design and create a class that holds these three ints, either as an array or as three member variables.
I would highly recommend to enclose the integer array of 3 numbers into a meaningful class, that would hold, display and control an array of 3 integers.
Then in your main, you can have an growing ArrayList of objects of that class.
You have an extra ) here:
element = (int[])it.next()); //with the extra parenthesis the code will not compile
should be:
element = (int[])it.next();
Besides the problem in the other answer, you cal it.next() two times, that cause the iterator move forward two times, obviously that's not what you want. The code like this:
element = (int[])it.next());
String el = (String)element;
But actually, I don't see you used el. Although it's legal, it seems meaningless.

Categories