Need little help. Working on my homework and I have to sort list using ArrayDeque. I can check first and last element.
I have a list, for example
int[] list = {6, 8, 7};
First element - 6 - will go into empty array, no problem with that.
Second element - 8 - will go at behind the 6, so we will have[6,8], but then comes 7. Since I can't put it in front of the 6, and I cant put it behind 8. So I have to store 7 into some other list that I can later return. How do I do that? Any hint is welcome.
Thanks.
(And sorry if this is something that has been asked before, but couldn't find the solution)
Let me clarify your constraints first. You can only:
get the value of the first element
remove the first element
prepend before the first element
get the value of the last element
remove the last element
append after the last element
An algorithm to add values from an array into a structure described above, using a stack:
for each value in the array
if the value is smaller than the first in the deck -> prepend
else if the value is greater than the last in the deck -> append
else if the value is closer to the first:
remove the first element and push on the stack repeatedly, as long as the first element is smaller
prepend the value to the deck
while the stack is not empty, pop from it and prepend to the deck
else:
remove the last element and push on the stack repeatedly, as long as the last element is greater
append the value to the deck
while the stack is not empty, pop from it and append to the deck
If you are not allowed to use a stack, but you are allowed to use recursion, then you can use the call stack to the same end
Something you could do is to store the int value at index x into a local variable and then traverse through the array seeing if there is a value lower than the currently stored value and if so that becomes the new lower value. When it finishes going through the array you can input that into the new array.
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
ArrayDeque<Integer> container = new ArrayDeque<>();
ArrayDeque<Integer> container2 = new ArrayDeque<>();
System.out.println("Please enter 10 number with space");
for(int i=0;i<10;i++){
container.add(sc.nextInt());
}
while (!isSorted(container.isEmpty()?container2:container)) {
while (!container.isEmpty()) {
int a = container.poll();
if(container.peek()!=null && a<container.peek()){
if(container2.peek()!=null && container2.peek()>container.peek()){
container2.addFirst(a);
}else{
container2.addLast(a);
}
}else if(container.peek()!=null){
if(container2.peek()!=null && container2.peek()>container.peek()){
container2.addFirst(container.poll());
}else{
container2.addLast(container.poll());
}
container.addFirst(a);
}else{
container2.addLast(a);
}
}
while (!container2.isEmpty()) {
int a = container2.poll();
if(container2.peek()!=null && a<container2.peek()){
if(container.peek()!=null && container.peek()>container2.peek()){
container.addFirst(a);
}else{
container.addLast(a);
}
}else if(container2.peek()!=null){
if(container.peek()!=null && container.peek()>container2.peek()){
container.addFirst(container2.poll());
}else{
container.addLast(container2.poll());
}
container2.addFirst(a);
}else{
container.addLast(a);
}
}
}
while (!container.isEmpty()) {
System.out.println(container.poll());
}
System.out.println("---------------------------");
while (!container2.isEmpty()) {
System.out.println(container2.poll());
}
}
static boolean isSorted(ArrayDeque<Integer> con){
boolean answer = true;
for(int i=0;i<con.size()-1;i++){
int a = con.poll();
con.addLast(a);
if(con.peek()!=null && a>con.peek()) answer= false;
}
con.addLast(con.poll());
return answer;
}
Related
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);
}
}
Is there a way to increase the for-loop range in java? I have the following code:
for (DataRoot bri : Ri)
{
for (DataRoot brcom : complemento)
{
if (bri.getMesa().equals(brcom.getMesa()))
{
if (found) {found = false; break;}
postrecom = brcom.getOrden().getPostres();
Calendar dateri = Calendar.getInstance();
Calendar datecom = Calendar.getInstance();
dateri.setTime(bri.getFechaorden());
for (Postres proc : postrecom)
{
// if (found) {found = false; break;}
datecom.setTime(proc.getHora_plato());
long diff = datecom.getTimeInMillis() - dateri.getTimeInMillis();
if ( diff > (3*60*1000))
{
found = true;
Ri.add(brcom);
break;
}
else
{
bri.getOrden().getPostres().add(proc);
setBase();
}
}
}
}
}
As you can notice, if some conditions are met, the Array "Ri" which is the main array will increase its content, lets say from 3 items to 4, at the start, the loop was going to be from 0 to 2 but as it got a new element I need it to keep running from 0 to 3 but the range will not dynamically increase as new items are added.
I could count how many items I added to "Ri" So that I can call that many times this method but if I do so, the compiler witll give me the "java.util.ConcurrentModificationException" error at this point I dont know what to do any help would be appreciated.
I might be wrong, but from the explanation you have given and code you have written, you are trying to get complement Items and then add them to Ri list if not present.
Assuming data structure of Ri is ArrayList, the way I would approach is that, first I would get all the complement items. Then loop through complement items, and for each complement item, loop through the entire Ri value and set a boolean if the associated value is suitable to add like below :
for(dataBri brCom : complemento) {
boolean shouldAdd = false;
for (DataBri bri : Ri) {
if(someConditionMet) {
shouldAdd = true;
}
if (shouldAdd) {
Ri.add(brCom);
}
}
I hope it makes sense.
Well im relatively new developing in Java and seems like if you do loop type For-each like
for (Arraylist arraylist : size)
{
....
}
assuming your initial size was 2, meaning that the array contains 2 elements, IF in the process you add elements to the array, the size wont dynamically change BUT if you go for the old
for (int i = 0; i < Arraylist.size(); i++)
{
....
}
and in the process you add elements to the Array, the size of the loop gets re-calculated dynamically as you add new elements to the array and in my case, solving my problem.
I need to remove duplicate elements from an array by adding elements that are not repeated in the original array to a new array and output the contents of that.
The problem I am having is that when the new array with no duplicates is printed there are zeros being outputted also.
Thus: does Java fill the array with zeros?
public static boolean hasDuplicates(int arrayNum[])
{
boolean dupFound = false;
int ctr1 =0;
while (ctr1<arrayNum.length && !dupFound)
{
int ctr2 = ctr1+1; // be 1 ahead each time ctr1 increments
while(ctr2<arrayNum.length)
{
if(arrayNum[ctr1] == arrayNum[ctr2])
dupFound = true;
ctr2++;
}
ctr1++;
}
return dupFound;
}
public static int[] removeDuplicates(int[] arrayNum)
{
if(hasDuplicates(arrayNum) == false)
return arrayNum;
else
{
int outArray[] = new int[arrayNum.length];
int ctr1=0;
int ctr2 = ctr1+1;
int index = 0;
boolean dupFound = false;
while(ctr1<arrayNum.length)
{
dupFound = false;
ctr2 = ctr1+1;
while(ctr2<arrayNum.length && !dupFound)
{
if(arrayNum[ctr1] == arrayNum[ctr2])
dupFound = true;
ctr2++;
}
if(dupFound == false)
{
outArray[index] = arrayNum[ctr1];
index++;
}
ctr1++;
}
return outArray;
}
}
public static void testRemoveDuplicates()
{
Scanner input = new Scanner(System.in);
System.out.println("Enter size of input array");
int array[] = new int[input.nextInt()];
System.out.println("Enter number of ints required");
for(int i=0; i<array.length; i++)
{
array[i] = input.nextInt();
}
int outArray[] = new int[array.length];
outArray = removeDuplicates(array);
for(int i=0; i<outArray.length; i++)
{
System.out.println(outArray[i]);
}
}
Here:
int outArray[] = new int[array.length];
That code assumes that you have exactly array.length array elements in your output array. And that is of course a too high number! The point is: when you create a new array of that size, the whole array is initially populated with 0 values. And your code will only "overwrite" a few slots of that output array; and all other slots stay at their initial 0 default value.
The point is: you first have to compute how many duplicates you have in your input array; and then you create a new array with exactly that number.
Alternatively, you could be using List<Integer> instead of int[]; as Java collections have the ability to grow dynamically. (or, you can keep increasing that array for collecting duplicates "manually"; that can be done, too - just a bit of complicated code to get there).
And the direct immediate answer is: yes, exactly - Java arrays are "pre-filled"; see here.
You can fix all of your problems (and probably make the code substantially faster in the process since it'll no longer have quadratic complexity) by using standard Java API calls to store the unique elements in a Set, and then turn the values in that set back into an array.
The main caveat is that you'd need to use Integer rather than int:
Set<Integer> s = new LinkedHashSet<Integer>(Arrays.asList(inputArray));
Integer[] outputArray = s.toArray(new Integer[0]);
The LinkedHashSet preserves insertion order, so you'll get the elements back in the same order as they originally appeared albeit without the duplicates.
May be you are wasting too much memory here by considering the worst case scenario where all input given are different while declaring the output array size. More Optimized Approach is that you can have an List<Integer> or ArrayList<Integer> which can store the unique values and then at last , If you want unique values in Array than declare the ArraySize same as the ArrayList<Integer> or List<Integer> size and just in one linear loop , You can copy all the data.
Does Java fill the array with zeros?
Yes , Whenever you declare the integer array , It will be having all its elements as 0. If you want to reset the value of Array to a particular value , You can use this method Arrays.fill(int array[] , int default_value). This can be done in O(list_size) complexity which is linear.
For your purpose more better approach would be use of HashSet<Integer> which holds only unique elements and which is Dynamic in nature so no need to waste extra space as well as it can make your work very easy.
So first you need to all elements in the HashSet<Integer> and then by using Iterator you can easily iterate through it but the insertion order can be disturbed here. So as replied by #Alnitak You can use LinkedHashSet<Integer> to have insertion order same.
A sample code using HashSet :
HashSet<Integer> set=new HashSet<Integer>();
int total_inputs=sc.nextInt();
for(int i=0;i<total_inputs;i++)
set.add(sc.nextInt());
Iterator itr=set.iterator();
while(itr.hasNext())
System.out.println((int)itr.next());
Note : Here input order will not be preserved.
Does Java fill the array with zeros?
Yes, java will initialize every element of your int array to 0. Therefore using arr.length will not work for you as it doesn't return the logical length of your array. You need to track the number of elements of your array yourself. The following line in your code has no meaning
int outArray[] = new int[array.length];
because outArray starts pointing to a different array as returned by your method removeDuplicates.
I need to remove duplicate elements from an array by adding elements
that are not repeated in the original array to a new array
The easiest thing you can do is the following way:
In your method removeDuplicates,
Find the highest number from the given input array, increment it by 1 and assign it to a variable.
int max = Arrays.stream(arrayNum).max().getAsInt() + 1;
Modify your if block from
if(arrayNum[ctr1] == arrayNum[ctr2])
dupFound = true;
to
if(arrayNum[ctr1] == arrayNum[ctr2]) {
dupFound = true;
arrayNum[ctrl] = max;
max++;
}
I know that if you have two HashSet the you can create a third one adding the two.However, for my purpose I need to change my previous HashSet, look for certain condition , and then if not met then change the set again.My purpose is that that I will give an input, say number 456, and look for digits(1 through 9, including 0).If I'm unable to find size 10 for the HashSet then I will multiply the number with 2 , and do the same.So I'll get 912; the size is 6 now(and I need to get all digits 1-9 & 0, i.e., size 10).Now I will multiply it by 3 and I get 2736 , the size is now 7.I keep doing so until I get size 10.At the time I get size 10, I will complete the loop and return the last number that concluded the loop, following the incremental multiplication rule.My approach is as follows.It has errors so won't run but it represents my understanding as of now.
public long digitProcessSystem(long N) {
// changing the passed in number into String
String number = Long.toString(N);
//splitting the String so that I can investigate each digit
String[] arr = number.split("");
// Storing the digits(which are Strings now) into HashSet
Set<String> input = new HashSet<>(Arrays.asList(arr));
// Count starts for incremental purpose later.
count =1;
//When I get all digits; 1-9, & 0, I need to return the last number that concluded the condition
while (input.size() == 10) {
return N;
}
// The compiler telling me to delete the else but as a new Java user so far my understanding is that I can use `else` with `while`loops.Correct me if I'm missing something.
else {
// Increment starts following the rule; N*1, N*2,N*3,...till size is 10
N = N*count;
// doing everything over
String numberN = Long.toString(N);
String[] arr1 = number.split("");
// need to change the previous `input`so that the new updated `HashSet` gets passed in the while loop to look for size 10.This is error because I'm using same name `input`. But I don't want to create a new `set` , I need to update the previous `set` which I don't know how.
Set<String> input = new HashSet<>(Arrays.asList(arr1));
// increments count
count++;
}
clear() input and add the new values. Something like
// Set<String> input = new HashSet<>(Arrays.asList(arr1));
input.clear();
input.addAll(Arrays.asList(arr1));
and
while (input.size() == 10) {
should be
if (input.size() == 10) {
Or your else isn't tied to an if.
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.