I am trying to compute pascal's triangle given a row number. I am using recursion.
My code is below:
public static List<Integer> getRow(int rowIndex) {
if (rowIndex == 1){
List <Integer> list = new ArrayList(rowIndex+1);
list.add(1);
return list;
}
else{
List<Integer> oldList = getRow(rowIndex -1);
List <Integer> list = new ArrayList(rowIndex+1);
int temp = 0;
list.add(0,1);
list.add(list.size()-1,1);
System.out.println("rowIndex "+rowIndex);
for (int i = 1; i < list.size()-1; i ++){
temp = oldList.get(i) + oldList.get(i-1);
list.add(i,temp);
}
return list;
}
}
It always returns [1,1] regardless of what row I am trying to get. I tried inserting print statements. I noticed the size of list is always 2 regardless of what rowIndex is.
List <Integer> list = new ArrayList(rowIndex+1);
Is the line above not the correct way to create an ArrayList? Seems like my arraylist always has size = 2;
you misunderstand how ArrayLists do work and you really should read the Javadoc.
In short, the constructor's parameter defines the initial size of the ArrayList in memory, not the max size. If you instantiate a new ArrayList<Integer>(2)it only means that the jvm allocates upfront enough space for two Integers, and that when you add a third element then the jvm will grow the size of the ArrayList in order to allow you to add more elements.
Further, you can access an ArrayList position with get() only if an element has been added at this position.
Finally, keep in mind that add at a specific position shifts right all elements. Thus if you add(10,1) then add(2,4), your first add will be shifted right.
Back to your question, if you absolutely want to use an ArrayList and not an array, you have to initialize your ArrayList with the right size, then set values at the right positions.
Here is a working solution :
// the method with your algorithm which has been slightly modified
public static List<Integer> getRow(final int rowIndex) {
// notice that I call a helper method which initialises correctly the ArrayList
final List<Integer> list = init(rowIndex);
if (rowIndex == 1) {
// notice that I set the value at a given position
// I can only do it because I initialised all values to 0 first
list.set(0, 1);
} else {
final List<Integer> previousRowList = getRow(rowIndex - 1);
// again, I set values...
list.set(0, 1);
list.set(rowIndex - 1, 1);
for (int i = 1; i < (list.size() - 1); i++) {
// set again...
list.set(i, previousRowList.get(i - 1) + previousRowList.get(i));
}
}
// lets print out the row
System.err.println(list);
// then return it
return list;
}
public static List<Integer> init(final int size) {
// passing the size is overkill, but well...
final List<Integer> list = new ArrayList<Integer>(size);
// fill the ArrayList with zeros
for (int i = 0; i < size; i++) {
list.add(i, 0);
}
// then return it
return list;
}
public static void main(final String[] args) {
getRow(Integer.parseInt(args[0]));
}
If you run it you'll get a (not so nice, but working) Pascal's triangle. Here follows the result if you want 11 rows :
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
[1, 6, 15, 20, 15, 6, 1]
[1, 7, 21, 35, 35, 21, 7, 1]
[1, 8, 28, 56, 70, 56, 28, 8, 1]
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
[1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1]
Hope it helps !
I think you're miss-interpreting the data structures.
And array list is a LIST implemented on top of an array. Setting the size of the array in the constructor is a way to give control to the developer for the initial size of the array (This is rarely necessary as the class manages the array size itself--so just leave out this argument). So the size of an array list is actually the size of the list, which is the number of elements, not the number of buckets in the underlying array which is specified in the constructor.
If you know the size of the array you want, and you want to get and add at specific locations, use a standard array, not an array list.
However, I think your code will work if you move
list.add(list.size()-1,1);
to after your for-loop (I'm actually surprised it doesn't throw an index out of bounds exception). And since you're going left to right, none of your adds need an index specified, since it'll just add it to the end of the existing list.
Related
I'm trying to generate an array of 5 non-repeating integers in Java, but there are still repeats when I run it. Here's my code so far:
public int[] generateCode(){
code[0] = (int)Math.round(Math.random()*8+1); // initialize first number so it won't be compared against
for(int i=1; i<code.length; i++){
code[i] = (int)Math.round(Math.random()*8)+1;
for(int j=0; j<i; j++){
while(code[i]==code[j]){
code[i] = (int)Math.round(Math.random()*8)+1;
}
} // end inner for loop
} // end outer for loop
return code;
} // end generateCode method
Any help is very much appreciated!
So, your for-loop is checking for repeated characters, BUT each time you generate a new value (in the while-loop) you're not checking to see if the value exits before j.
There are a number of possible ways you might address this issue, I prefer ones which uses Collections.shuffle, but assuming that you can't use features like Arrays, Collections, List, Set or possibly even streams, we need to work with what we have, arrays.
Since you have a small range of acceptable values which need to fit into an even smaller range, a simple solution might be to generate a "master" list of allowed values and randomly select a value from the master list, tracking which values you've already picked.
Sounds more complicated then it actually is, for example...
public int[] generateCode() {
int[] masterValues = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int[] codes = new int[5];
Random rnd = new Random();
int index = 0;
while (index < codes.length) {
int lookupIndex = 0;
do {
lookupIndex = rnd.nextInt(masterValues.length);
} while (masterValues[lookupIndex] == 0);
codes[index] = masterValues[lookupIndex];
masterValues[lookupIndex] = 0;
index++;
}
return codes;
}
This creates a "master" list of values. It then randomly calculates a "lookup" index, checks to see if the value in the master list is 0 or not, if not, it assigns it to the next index in the codes array and sets the value in the master list to 0, otherwise it generates a new random index and tries again. This all repeats till it fills the codes array
So doing something like...
System.out.println(Arrays.toString(generateCode()));
System.out.println(Arrays.toString(generateCode()));
System.out.println(Arrays.toString(generateCode()));
System.out.println(Arrays.toString(generateCode()));
could print (because it's "random")...
[8, 1, 4, 7, 5]
[9, 6, 2, 1, 8]
[6, 5, 9, 4, 7]
[2, 5, 3, 1, 4]
There are much easier ways to do this. Using a Set<Integer> would be one. Here is another.
List<Integer> list = new ArrayList<>(List.of(1,2,3,4,5,6,7,8));
Collections.shuffle(list);
System.out.println(list.subList(0,5));
prints something like
[4, 5, 8, 2, 1]
As was pointed out to me, you may not be allowed to use or know about collections. But I would recommend you at least make a helper method to check for duplicates to reduce the clutter. Something like the following:
public boolean contains(int[] arr, int n) {
for (int v : arr) {
if (v == n) {
return true;
}
}
return false;
}
Then you can keep checking the current value to be false before you add it. Once it works it also lets you focus on other aspects of your code.
I want is to display all consecutive sequences from a given array of ints.
Finally I want to display the longest one with text.
What I tried
I sorted the array and found all sequences.
I stored the found sequences into a new ArrayList.
Below is only a small piece of code, because I know the rest doesn't work:
int[] myArray = {202,203,204,205,206, 100, 1, 3, 200, 2, 4, 201, 5};
ArrayList<Integer> secuence = new ArrayList<>();
Arrays.sort(myArray);
for (int i = 0; i < myArray.length - 1; i++) {
if ((myArray[i] + 1) == myArray[i + 1] || (myArray[i] - 1) == myArray[i - 1]) {
secuence.add(myArray[i]);
}
}
I tried many different ways, but can't figure out.
A couple remarks, suggestions:
As sort() sorts the array in increasing order, actually you do not have to check for decreasing elements
For finding the "anything"est thing, you need to store the "anything"est thing found so far, and a current candidate. This applies to finding largest element or longest sequence of consecutive elements too
For dealing with subparts of an array, it is not necessary to make an actual copy of the elements, it is enough to store beginning index and ending index or length.
Putting them together:
var myArray = [202,203,204,205,206, 100, 1, 3, 200, 2, 4, 201, 5];
myArray.sort((a,b)=>a-b);
console.log("Sorted array:",...myArray);
var longstart=0;
var longlength=0;
var currstart=0;
while(currstart<myArray.length){
var currlength=0;
while(currstart+currlength<myArray.length
&& myArray[currstart]+currlength==myArray[currstart+currlength])
currlength++;
if(currlength>longlength){
longlength=currlength;
longstart=currstart;
}
console.log("Sequence:",...myArray.slice(currstart,currstart+currlength));
currstart+=currlength;
}
console.log("Longest:",...myArray.slice(longstart,longstart+longlength));
This code is JavaScript so it can be run here, a Java variant (just with less printing) would look very similar:
int[] myArray = {202,203,204,205,206, 100, 1, 3, 200, 2, 4, 201, 5};
Arrays.sort(myArray);
int longstart=0;
int longlength=0;
int currstart=0;
while(currstart<myArray.length){
int currlength=0;
while(currstart+currlength<myArray.length
&& myArray[currstart]+currlength==myArray[currstart+currlength])
currlength++;
if(currlength>longlength){
longlength=currlength;
longstart=currstart;
}
currstart+=currlength;
}
for(int i=0;i<longlength;i++)
System.out.print((i==0?"Longest: ":", ")+myArray[longstart+i]);
The key thing is to have the check work with a growing distance, so the fixed [i]+1==[i+1] check in your initial code became [i]+distance==[i+distance].
I approached the solution as follows:
Data structures
a consecutive sequence (what we want to find) is a List of at least 2 consecutive Integers (pair)
to return all foundSequences you need one result List containing 0 or more Lists
to check for consecutive-ness you need the current and previous element
Algorithm
Logic applied (if):
Consecutive-ness is found if current == previous + 1, otherwise an existing consecutive sequence is broken
If a sequence has at least 2 elements, i.e. sequence.size() > 1, then it should be added to the result list (i.e. foundSequences)
Before the first element and after each broken sequence, the previous == null
After the last element there could be an open sequence with sequence.size() > 1. If so, then this sequence is not broken, but completed and should be added to the result list (i.e. foundSequences)
Iterating over elements (loop):
Use a for-each loop to process all elements of the (sorted!) array
The for-loop automatically fills the current element (iterating variable)
You must keep track of the previous element (thus initialized null before the loop). It must archive the current element of each loop, so we can compare the next element against it.
Unless the current element is not consecutive anymore (a break happened), then the previous will become null to start a fresh collection.
In case of a break the currently found sequence may be added to the result. Then the sequence needs to be reset to null to start a fresh collection.
After the last element was checked and the loop ended, there could be still a sequence (that was not yet broken). This needs to be added to the result.
8.
Source
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
class ConsecutiveSequenceFinder {
private int[] unsortedNumbers;
public ConsecutiveSequenceFinder(int[] numbers) {
this.unsortedNumbers = numbers;
}
public int[] sorted() {
int[] sortedNumbers = Arrays.copyOf(this.unsortedNumbers, this.unsortedNumbers.length);
Arrays.sort(sortedNumbers);
return sortedNumbers;
}
public List<List<Integer>> findSequences() {
// one sequence is List of integers; thus list of sequences is list of list of integers
List<List<Integer>> foundSequences = new ArrayList<>();
// first we sort the array
int[] ascending = this.sorted();
// this working variable will hold the currently found sequence
List<Integer> sequence = new ArrayList<Integer>();
Integer previous = null;
System.out.println("Finding sequences ..");
for (int current : ascending) {
// check if current value is first or one more than (consecutive to) previous
if (previous == null || current == previous + 1) {
sequence.add(current);
previous = current;
} else {
System.out.printf("\tsequence of %d consecutive is broken at: %d\n", sequence.size(), current);
// if sequence found (at least a pair) then add
if (sequence.size() > 1) {
foundSequences.add(sequence);
}
// and finally prepare a new sequence, to collect fresh again
sequence = new ArrayList<>();
previous = null;
}
}
// if sequence left, then add
if (sequence.size() > 1) {
System.out.printf("\tsequence of %d consecutive was completed with last array element\n", sequence.size());
foundSequences.add(sequence);
}
return foundSequences;
}
public static void main (String[] args) throws java.lang.Exception {
// demo numbers
int[] values = {202,203,204,205,206, 100, 1, 3, 200, 2, 4, 201, 5};
// starting demo
System.out.println("Input: " + Arrays.toString(values));
ConsecutiveSequenceFinder finder = new ConsecutiveSequenceFinder(values);
System.out.println("Sorted: " + Arrays.toString(finder.sorted()));
List<List<Integer>> foundSequences = finder.findSequences();
System.out.println("Found sequences: " + foundSequences.size());
// print for each sequence the size and its elements
for (List<Integer> sequence : foundSequences) {
System.out.printf("\t %d elements: %s\n",sequence.size(), sequence.toString());
}
// check for each sequence if it is the longest
List<Integer> longestSequence = new ArrayList<>();
for (List<Integer> sequence : foundSequences) {
if (sequence.size() > longestSequence.size()) {
longestSequence = sequence;
}
}
System.out.printf("Longest sequence has %d elements: %s\n",longestSequence.size(), longestSequence.toString());
}
}
Actual Output
Input: [202, 203, 204, 205, 206, 100, 1, 3, 200, 2, 4, 201, 5]
Sorted: [1, 2, 3, 4, 5, 100, 200, 201, 202, 203, 204, 205, 206]
Finding sequences ..
sequence of 5 consecutive is broken at: 100
sequence of 7 consecutive was completed with last array element
Found sequences: 2
5 elements: [1, 2, 3, 4, 5]
7 elements: [200, 201, 202, 203, 204, 205, 206]
Longest sequence has 7 elements: [200, 201, 202, 203, 204, 205, 206]
Process finished with exit code 0
I see a lot of posts with the same topic (mostly with Strings) but haven't found the answer to my question. How would I remove duplicate integers from an ArrayList?
import java.util.*;
public class ArrayList2 {
public static ArrayList<Integer> removeAllDuplicates(ArrayList<Integer> list) {
Collections.sort(list);
for (int i = 0; i < list.size(); i++) {
if (list.get(i) == list.get(i + 1)) {
list.remove(i);
}
}
return list;
}
}
This is the start of my code, the only problem that has arised is that if there are 3 integers with the same value, it only removes one of them. If I put in 4, it removes two of them. PLEASE NO HASHING!!!
The ArrayList and the output when I run it:
List: [-13, -13, -6, -3, 0, 1, 1, 1, 5, 7, 9]
Duplicates Removed: [-13, -6, -3, 0, 1, 1, 5, 7, 9]
This is my first time using this website, so please let me know if I'm doing something wrong with formatting/if there's already an answer to my question that I missed.
The specific reason why your removeAllDuplicates function doesn't work is that you are still iterating after a successful comparison. If you iterate only when list.get(i) != list.get(i + 1), you will get rid of all the duplicates.
public static ArrayList<Integer> removeAllDuplicates(ArrayList<Integer> list) {
Collections.sort(list);
int i = 0;
while(i < list.size() - 1) {
if (list.get(i) == list.get(i + 1)) {
list.remove(i);
} else {
i++;
}
}
return list;
}
It's worth noting that the above function is not as fast as it could be. Though the iteration runs quickly enough, the most significant step will be the sort operation (O(n log n)).
To avoid this extra time complexity, consider using a HashSet instead of an ArrayList (if it still fits within the constraints of your problem).
Other people have "answered" the basic issue, of the if statement skipping over elements because the for-loop is incrementing the index position, while the size of the array is shrinking.
This is just "another" possible solution. Personally, I don't like mutating Lists in loops and prefer to use iterators, something like...
Collections.sort(list);
Iterator<Integer> it = list.iterator();
Integer last = null;
while (it.hasNext()) {
Integer next = it.next();
if (next == last) {
it.remove();
}
last = next;
}
Still, I think some kind of Set would be a simpler and easier solution (and since you'd not have to sort the list, more efficient ;))
This assumes that you cannot use a set ("Please No hashing!!!") for a reason such as homework.
Look what happens when you remove a duplicate. Let's say that the dupe you're removing is the 1st of 3 consecutive equal numbers.
v
-13, -6, -3, 0, 1, 1, 1, 5, 7, 9
Here i is 4 to refer to the first of the 3 1 values. When you remove it, all subsequent elements get shifted down, so that the second 1 value now takes the place of the first 1 value at index i = 4. Then the current iteration ends, another one begins, and i is now 5.
v
-13, -6, -3, 0, 1, 1, 5, 7, 9
But now i is referring to the second of the two 1 values left, and the next element 5 isn't equal, so no dupe is found.
Every time you find a duplicate, you must decrease i by 1 so that you can stay on the first element that is a duplicate, to catch 3 or more duplicates in a row.
v
-13, -6, -3, 0, 1, 1, 5, 7, 9
Now consecutive elements still match, and another 1 value will get removed.
You'd want to have a double for loop as you dont want to check the only the next index but all indexes. As well as remember when you remove a value you want to check that removed value again as it could of been replaced with another duplicate value.
I came across the following problem. I have an ArrayList(1) of ArrayLists(2). What I need to do is, to sort the structure so that the first elements of ArrayLists(2) to be in ascending order going down ArrayList(1). To clarify:
Input:
3, 8, 6
2, 14, 205, 44, 1
1, 3
Output:
1, 3
2, 14, 205, 44, 1
3, 8, 6
Look how it sorts the rows only based on the first value.
For now the way the arraylist of arraylists is defined for me is:
List<List<Integer>> graph = new ArrayList<List<Integer>>();
// and I add elements to it likewise
graph.get(currentIndex).add(new ArrayList<Integer>());
The reason I am using ArrayList is because I read that it is more memory efficient than LinkedList and because I am building a list of adjacency lists of a graph. In it both either the number of nodes can vary or the length of the adjacency list per node. The first element of a row is the start_node, the following - its adjacent. Could you please tell me how can I implement this sorting?
So as I understand it, you want to sort the top-level list by the first element of each nested list. Is this correct? Here is how I would go about it:
List<List<Integer>> graph = new ArrayList<List<Integer>>();
// add a bunch of things ...
// ...
// Now, to sort:
graph.sort((x,y) -> Integer.compare(x.get(0), y.get(0)));
This is using Integer to get a Comparator, which is what the sort() method requires to sort by some custom criteria. In this case, we are telling it to sort the List of Lists graph by comparing two arbitrary items in graph by getting their first items and comparing them as you normally compare Integers.
Note that this assumes all items in graph have a first item.
To compare 2 sublist you need to find the first non-equal pair, and compare their value (if both starts with like 32, you need to look next value to see)
List<List<Integer>> graph = new ArrayList<>();
graph.add(Arrays.asList(3, 8, 6));
graph.add(Arrays.asList(2, 14, 205, 44, 1));
graph.add(Arrays.asList(2, 14, 205, 44, 2));
graph.add(Arrays.asList(1, 3));
graph.add(Arrays.asList(1, 4));
graph.add(Arrays.asList(1, 4));
graph.add(Arrays.asList(1, 4, 5));
graph.sort((o1, o2) -> {
int indice, cmp, min;
for (indice = 0, min = Math.min(o1.size(), o2.size());
indice < min; indice++) {
if ((cmp = Integer.compare(o1.get(indice), o2.get(indice))) != 0) {
return cmp;
}
}
if (indice == o1.size()) return -1;
if (indice == o2.size()) return 1;
return 0;
});
System.out.println(graph);
[[1, 3],
[1, 4],
[1, 4],
[1, 4, 5],
[2, 14, 205, 44, 1],
[2, 14, 205, 44, 2],
[3, 8, 6]]
As side, another way using Comparator interface (I agree this is not very nice), it compares the value until one of the list if empty, then it will compare the size if it reaches one fully
graph.sort((o1, o2) -> {
Comparator<List<Integer>> cc = Comparator.comparingInt(l -> l.get(0));
int indice, min;
for (indice = 0, min = Math.min(o1.size(), o2.size()); indice < min; indice++) {
final int i = indice;
cc = cc.thenComparingInt(l -> l.get(i));
}
return cc.thenComparingInt(List::size).compare(o1, o2);
});
So, here is another solution I came up with.
The idea is: use the Collections' static method sort() and feed it in with the reference to the list and a new Comparator object with defined by us compare().
Collections.sort(graph, new Comparator<List<Integer>>(){
#Override
public int compare(List<Integer> aList1, List<Integer> aList2) {
return aList1.get(0).compareTo(aList2.get(0));
}
}));
I have an integer array of size 4. I am adding elements to it via the add method. This is as an unsorted array. I am sorting it via the sort method shown in the code below. The sort method places the smallest number in the position a[0]. When I try to add elements after I call the sort method I always get a return value of 0. Is there a way around this?
import java.util.Arrays;
public class Scrap {
private static int[] array = new int[4];
private static int i = 0;
public static void main(String[] args) {
Scrap pq = new Scrap();
pq.add(4);
pq.insert(3);
pq.add(5);
pq.sort();// smallest to largest sort method.
// System.out.println(array[0]);
pq.insert(1);
pq.sort();
int test = pq.Minimum();
System.out.println("The smallest element of the array is " + test);
pq.sort();
}
//
public void add(int input) {
insert(input);
}
// Method to insert number into the array.
public void insert(int input) {
array[i] = input;
i++;
}
// Finding smallest number of the array.
public int Minimum() {
int a = array[0];
return a;
}
// Sorts the array from smallest to largest integer
public void sort() {
int first, temp;
for (int i = array.length - 1; i > 0; i--) {
first = 0;
for (int j = 1; j <= 1; j++) {
if (array[j] > array[first])
first = j;
}
temp = array[first];
array[first] = array[i];
array[i] = temp;
}
}
public int remove() {
return delete();
}
public int delete() {
return remove();
}
// Method to convert the array into a string for output
}
The problem in a nutshell:
You start with an array of length 4.
At this point the array contains 4 zeros, that is: [0, 0, 0, 0]
You add 4, 3, and 5. These operations update the content of the array to [4, 3, 5, 0].
You sort the array. This should change the content of the array to [0, 3, 4, 5]. In fact it changes to [0, 5, 3, 4], which means your implementation of sort is clearly broken.
You probably didn't expect the 0 value to move. You can fix this by sorting only the first 3 values. (And, of course, you should also fix your implementation of sort.)
Then when you insert 1, the program updates the value at index 3, so the content changes to [0, 5, 3, 1].
If you implement the fix I suggested above, and sort only the first size elements, then the content after the first call to sort should become [3, 4, 5, 0], and the content after the insert 1 should become [3, 4, 5, 1]. And when you sort that again, the content should become [1, 3, 4, 5] and the smallest value will be 1 as expected, instead of 0.
More concretely:
First of all, change private static int i = 0; to private int size = 0;. The name i is extremely inappropriate here, and will surely confuse you. size is appropriate. It also doesn't make sense to make it static, so I suggest to drop that keyword.
Fix the implementation of sort. There are many basic sorting algorithms that are easy to implement. In the implementation, instead of going until array.size, go until size. Do you see the difference? size is the field in Scrap, essentially it's the number of elements you added using the add or insert methods.
Some cleaning up would be good too:
Delete the add method and rename insert to add.
Delete the remove and delete methods. They are not used, and you will get a stack overflow if you try to use them as they are now (the methods call each other, forever)
Look at the content of the array after each step in the program.
After Scrap pq is created, this is the content of its array:
[0, 0, 0, 0]
Then a couple of modifications:
pq.add(4);
pq.insert(3);
pq.add(5);
The content at this point:
[4, 3, 5, 0]
So far so good.
Then you sort it:
pq.sort();
The content at this point:
[0, 5, 3, 4]
Ouch. The sort implementation doesn't work very well, does it. But let's ignore that for now. Next step:
pq.insert(1);
The content at this point:
[0, 5, 3, 1]
None of this behavior makes sense, probably this is not how you intended the program to work. Review the program, verify the content after each step. Do not proceed to the next step until the current step is working correctly.
I am assuming that you will be using a correct sort method (because, this is not correct, you can use Arrays.sort). But still with a correct sort, there is a logical problem in your code.
At the beginning, the array contains all 0s. After adding the first 3 int, when you call the sort method, the array contains the values in following order:
0,3,4,5
Note that, the value of i is not changed. At this state the value of i is 3. So when you insert 1, the new values become
0,3,4,1
So after sorting again, the values of arrays become
0,1,3,4
So obviously the minimum will retrun 0
I don't think that is the most effective way to sort an array. It is possible to do this with just 1 for loop. Try this to sort your array from smallest to largest.
int temp;
for(int i=0;i<array.length-1;i++){
if(array[i]>array[i+1]){
temp=array[i];
array[i]=array[i+1];
array[i+1]=temp;
i=-1;
}
}