I know the rationale behind nested loops, but this one just make me confused about the reason it wants to reveal:
public static LinkedList LinkedSort(LinkedList list)
{
for(int k = 1; k < list.size(); k++)
for(int i = 0; i < list.size() - k; i++)
{
if(((Birth)list.get(i)).compareTo(((Birth)list.get(i + 1)))>0)
{
Birth birth = (Birth)list.get(i);
list.set( i, (Birth)list.get( i + 1));
list.set(i + 1, birth);
}
}
return list;
}
Why if i is bigger then i + 1, then swap i and i + 1? I know for this coding, i + 1 equals to k, but then from my view, it is impossible for i greater then k, am i right? And what the run result will be looking like? I'm quite confused what this coding wants to tell me, hope you guys can help me clarify my doubts, thank you.
This method implements a bubble sort. It reorders the elements in the list in ascending order. The exact data to be ordered by is not revealed in this code, the actual comparison is done in Birth#compare.
Lets have a look at the inner loop first. It does the actual sorting. The inner loop iterates over the list, and compares the element at position 0 to the element at position 1, then the element at position 1 to the element at position 2 etc. Each time, if the lower element is larger than the higher one, they are swapped.
After the first full run of the inner loop the largest value in the list now sits at the end of the list, since it was always larger than the the value it was compared to, and was always swapped. (try it with some numbers on paper to see what happens)
The inner loop now has to run again. It can ignore the last element, since we already know it contains the largest value. After the second run the second largest value is sitting the the second-to-last position.
This has to be repeated until the whole list is sorted.
This is what the outer loop is doing. It runs the inner loop for the exact number of times to make sure the list is sorted. It also gives the inner loop the last position it has to compare to ignore the part already sorted. This is just an optimization, the inner loop could just ignore k like this:
for(int i = 0; i < list.size() - 1; i++)
This would give the same result, but would take longer since the inner loop would needlessly compare the already sorted values at the end of the list every time.
Example: you have a list of numbers which you want to sort ascendingly:
4 2 3 1
The first iteration do these swap operations: swap(4, 2), swap(4, 3), swap(4, 1). The intermediate result after the 1st iteration is 2 3 1 4. In other words, we were able to determine which number is the greatest one and we don't need to iterate over the last item of the intermediate result.
In the second iteration, we determine the 2nd greatest number with operations: swap(3, 1). The intermediate result looks then 2 1 3 4.
And the end of the 3rd iteration, we have a sorted list.
Related
public class TestPossibleNumbers {
public static void main(String[] args) {
int input[] = { 1, 2, 3 };
// int input[] = {10,11,12,13};
possibleNumbers(input, 0);
}
public static void possibleNumbers(int[] x, int index) {
if (index == x.length) {
for (int i = 0; i < x.length; i++) {
System.out.print(x[i] + " ");
}
System.out.println();
}
for (int i = index; i < x.length; i++) {
int temp = x[index];
x[index] = x[i];
x[i] = temp;
possibleNumbers(x, index + 1);
temp = x[index];
x[index] = x[i];
x[i] = temp;
}
}}
Can anyone help me to understand the code inside for loop?
This program run perfectly. But, I am unable to figure out how it is working
You are recursively calling the method again at:
possibleNumbers(x, index + 1);
Thus the method runs the method again, with index + 1 passed. It checks if
if(index == x.length)
If the statement is correct it prints the numbers.
It then enters the 2nd for loop again(if the if statement was incorrect it will still enter it). And calls the recurring method again. It will keep entering 2nd for loop but when "index" will be equal to or greater than "i.length" no iterations of the for loop will run because you specified for loop to run only when:
i<i.length
When 2 for loop does not do any iterations the method will stop recurring. So in your case when index is equal to 3 no iterations of 2nd for loop will run.
Try running debug step by step to see what is happening more in depth.
The Program prints permutation of numbers not combination.
Permutation - Order matters
Combination - Order doesnt matter and more of choosing k elements out of n
for example
int a= {a,b};
permutation = {ab,ba}
whereas combination ={{},{a},{b},{a,b}}
To understand how the program works
go through the following link will
https://www.geeksforgeeks.org/write-a-c-program-to-print-all-permutations-of-a-given-string/
Don't get confused on recursion inside for loop.
if (index == x.length) is the terminating condition for recursion.
Inside the for loop before and after calling the recursive call possibleNumberselements are swapped.
Before swap helps to generate all possible outcomes and after swap elements will swap to previous position so that all other permutation will be generated from the for loop. It may sounds confusing please go through the link.
I'll provide an alternative explanation that I feel is more intuitive.
Consider the case of only 1 number in the list: [a]. This is pretty trivial: there's a single combination [a].
Now consider the case of 2 numbers in the list: [a, b]. In this case you can take each of the elements in turn and then look at all combinations of the remaining element using the previous method and then add the element back.
Now consider the case of 3 numbers in the list: [a, b, c]. In this case you can take each of the elements in turn and then look at all combinations of the other 2 elements using the previous method and then add the element back.
And so on for 3, 4, 5... elements.
So, in general, consider the case of n numbers in the list: [a1, a2, ... an]. In this case take each of the elements in turn and then look at all combinations of the other n-1 elements using the exact same method and then add the element back.
Converting to pseudo code:
getCombos(values)
for each value
for each combo in getCombos(values with value removed)
add value + combo to results
return results
The only thing to add is the base case which is necessary for all recursive implementations. One possibility is the case of a single item. However there's an even simpler one: if there are no values then the result is a single empty list.
So converting that to Java, using sets to make clear that the elements need to be unique (to avoid duplicate results), using streams and making it generic so it'll work for any type:
Stream<List<C>> combos(Set<C> values) {
if (values.isEmpty())
return Stream.of(new ArrayList<>());
else
return values.stream().flatMap(value ->
combos(values.stream()
.filter(v -> !v.equals(value))
.collect(toSet())).peek(r -> r.add(value)));
}
Your code is really just an alternate implementation of the same algorithm that swaps the element under consideration to the front of the array instead of creating a new collection.
I have a pseudo code that I have translated into java code but anytime I run the code, I get an empty arraylist as a result but it is supposed to give me a random list of integers.
Here is the pseudo code:
Algorithm 1. RandPerm(N)
Input: Number of cities N
1) Let P = list of length N, (|P|=N) where pi=i
2) Let T = an empty list
3) While |P| > 0
4) Let i = UI(1,|P|)
5) Add pi to the end of T
6) Delete the ith element (pi) from P
7) End While
Output: Random tour T
Here is the java code:
public static ArrayList<Integer> RandPerm(int n)
{
ArrayList<Integer> P = new ArrayList<>(n);
ArrayList<Integer> T = new ArrayList<>();
int i;
while(P.size() > 0)
{
i = CS2004.UI(1, P.size());// generate random numbers between 1 and the size of P
T.add(P.get(i));
P.remove(P.get(i));
}
return T;
}
I don't know what I am doing wrong.
ArrayList<Integer> p = new ArrayList<>(n);
... creates an empty list with an initial capacity of n.
All this does is tell the ArrayList what size array to initialise as backing store - most of the time you achieve nothing useful by specifying this.
So your while(p.size() > 0) runs zero times, because p.size() is zero at the start.
In the pseudocode "where pi=i" suggests to me that you want to initialise the list like this:
for(int i=0;i<n;i++) {
p.add(i)
}
(I have lowercased your variable name - in Java the convention is for variables to startWithALowerCaseLetter -- only class names StartWithUpperCase. It's also the Java convention to give variables descriptive names, so cityIdentifiers perhaps)
You may want to know that, even if you fix the problem that P is always empty, there are 2 more issues with your implementation.
One is that P.remove(P.get(i)) does not necessarily remove the ith item if the list has equal value items. It scans from the beginning and removes the first occurrence of the item. See ArrayList.remove(Object obj). You should use P.remove(i) instead for the correct results.
Then the performance is O(n^2). The reason is that ArrayList remove an item by shifting all the subsequent items one slot to the left, which is an O(n) operation. To get a much better performance, you can implement your own "remove" operation by swapping the item to the end. When you generate the next random index, generate it within the range [0, beginning index of the removed items at the end). Swapping is O(1) and the overall performance is O(n). This is called Knuth Shuffle by the way.
I have a question that doesn't seem possible to me. I have 2+ arrays which I have to compare for common values. I am supposed to do this in O(N) comparisons but can't think of a way. Specifically (k-1)N comparisons where k is the number of arrays. I've narrowed down how I can take multiple arrays and just merge them into a single array. I've gotten that the smallest array is the limiting factor so if I sort that I can save the most comparisons. After spending half the day staring at my screen I've even come up with a way to do this linearly if I discount any duplicates, but I have to keep duplicates So, as far as I know in order to compare any arrays you need at least 2 for loops which would be O(N^2) wouldn't it? I'm also not allowed to hash anything.
For example if I had {1,3,4,3,4,5} as a master and {1,1,3,5,9,3,7} and {3,5,8,4,0,3,2} as arrays to be compared I'd need to have a final of {3,3,5} since I can't get rid of any dupiclates.
I don't want anyone to write the code, I just need to know what I should be doing in the first place.
Use an array of ints. Taking your first list, for each element, set the value at that index to 1. So if the first element is 3, put 1 in array[3]. Now, we know that 3 is present in first list. Putting 1 will help you distinguish from a 3 that is present in the earlier list versus a 3 which is repeated in current list.
Iterate through all the other k-1 lists
For every element, check the value in array for that index
If the value is 0, set it to this list number
If the value is a number less than this list number, this number is a duplicate and has already appeared in a previous list.
If this number is equal to this list index it means this number already occurred in this list but not in previous lists, so not yet a duplicate.
The numbers that you are getting as duplicates, add them to another list.
Finish all iterations
Finally print the duplicates.
Original Wrong Answer
Create a HashSet<int>
Take all values from master and add to it - O(master list count)
Now just iterate through first and second arrays and see if their elements are in that HashSet - O(each list count)
If the lists are sorted, then it's relatively straightforward if you do something like this:
List<Integer> intersection = new ArrayList<>();
int i = 0;
int j = 0;
while (i < list1.size() && j < list2.size()) {
int a = list1.get(i);
int b = list2.get(j);
if (a < b) {
i++;
} else if (b < a) {
j++;
} else { // a == b
intersection.add(a);
i++;
j++;
}
}
On each iteration of the loop, the quantity i + j increases by at least 1, and the loop is guaranteed to be done when i + j >= list1.size() + list2.size(), so the whole thing does at most O(list1.size() + list2.size()) comparisons.
is there a way to compare two arrayLists to see if either of them have equal values at any point? I know that I can use two nested loops, however I am trying to do this in log(n) time, so instead, I am trying to do it similarly to how one would merge two lists in mergesort, however I can't really figure out exactly how to implement it. Any help would be greatly appreciated! Thanks!
Edit: Yeah I meant nlog(n), not log(n), sorry
You can't do it in O(log(n)).
You can implement this with O(n*log(n)) by first sorting both list and then comparing them element-wise (sorting takes nlogn and comparing n)
You can do it like this:
create to variables i, j initialized with 0
loop over the lists and compare l1.get(i) with l2.get(j)
3a. equal: increment both i, j (and maybe memorize the tuple)
3b. element of l1 is smaller than the element of l2: increment i only
3c. element of l1 is greater than the element of l2: increment j only
exit loop, if one index is out of bounds
You don't need to scan the list for the index that was not out of bounds, since you are just interested in the equal values.
If you want to compare whether the values are the same at any point (ie, object at index 1 of list 1 == object at index 1 of list 2) then you'd just loop over the lists and compare (O(N))
If you want to find out whether they have any values in common, sort both and walk down the lists. O (n log n), because of the sorting.
if both list are of same size then
for(int i =0; i<listOne.size();i++) {
int index = listTwo.indexOf(listOne.get(i));
if(index !=-1) {
System.out.println("equal at listOne[" + i + "] and listTwo[" + index + "]");
}
}
What about Heap? Then just merge that heaps.
I'm still learning about sorting and Arrays. Came up with this code which does sorting letters or numbers on ascending order but I really don't get the last part where System.out.println(SampleArray[i]);. Why is it SapleArray[i]? can someone enlighten me please.
public class TestClass {
public static void main(String[] args) {
String SampleArray[] = {"B","D","A","R","Z"};
Arrays.sort(SampleArray);
for (int i=0; i < SampleArray.length; i++) {
System.out.println(SampleArray[i]);
}
}
}
SampleArray refers to the whole array - here containing five strings.
SampleArray[0] refers to the first item in the array (here the string "B").
for (int i=0; i < SampleArray.length; i++) {
System.out.println(SampleArray[i]);
}
lets i take the values 0, 1, 2, 3, 4 one after another, so you print out first SampleArray[0]and then SampleArray[1] and so on until all the items have been printed.
You are trying to print an array, which is an ordered collection of items.
SampleArray[i] inside the loop lets you access one element at a time, in order.
More specifically, i takes on the values 0 through 4 in this case.
SampleArray[0] would give you the first element of SampleArray, because Java uses zero-based indexing for arrays.
Going through your code:
first you create a String array with those letters as element, which are saved like this: element 0 of array = B, element 1= D, etc. (in Arrays the counting always begin by 0 and not by 1).
Then it sort it in ascending order.
The for loop is there to print the sorted array, it iterate through the array beginning by element 0, until it is at the last element of the Array and it print these element.
The for loop does something over and over again.
The first part of the for loop, int i = 0 sets up a variable.
The second part i < SampleArray.length is the 'terminating condition' - it's the condition that has to remain true before each iteration of the loop.
The last part i++ is what happens after each iteration - i gets incremented.
So we are printing each element within SampleArray. i goes between 0 and the one less than the number of elements in the array. (e.g. if the array contained 4 elements, i would be 0 to 3, which is what we want).
And in the body of the loop, the [i] bit selects that element from SampleArray, and that is the value that gets printed on each line.
Another way of looking at it: SampleArray supports the [] operator, which when applied, will return an element from the array.