Explaining how insertion sort works - java

I need to understanding the algorithm for insertion sort.
If someone can explain in layman terms how this code breaks down.
public void insertionSort() {
int in, out;
for(out=1; out<nElems; out++) {
long temp = a[out];
in = out;
while(in>0 && a[in-1] >= temp){
a[in] = a[in-1]; // shift item right,
--in;
a[in] = temp; } // end for
I would like to know in particular why
What i do not understand is, in other sorts we use the for loop, and in this one we are using while loop in this particular sort?
2.a[in-1] >= temp, are they using this because we have removed one element?

What i do not understand is, in other sorts we use the for loop, and
in this one we are using while loop in this particular sort?
Humm no. Some sort implementations don't even have a loop. In this particular case they use a while loop because the number of iterations is not known in advance, but in Java the for loop can do the exact same things as a while loop so it's just a matter of readability
a[in-1] >= temp, are they using this because we have removed one
element ?
Because they perform a shift, which is always done by storing one of the shifted elements in a temporary variable. This is probably the most classical programming trick :
a = 5, b = 6
tmp = a
b = a
a = tmp
// now a is 6 and b is 5

while loops and for loops are (essentially) equivalent, because you can always do:
for(int i = 0; i < n; i++)
as
int i = 0
while (i < n) {
...
i++;
}
(The scope of int i is a little different e.g. in Java because in for loops its scope of i is only inside the the loop.)
It is not. The algorithm is trying to move the current value backwards in the array.
I think the Wikipedia article and this picture inside it is very helpful in understanding the concept.

Well, depending on how a while loop is structured, it can serve the same purpose as for loop. Additionally, most sorts utilize recursion. My advice to you is
1) Look up insertion sort, basic enough but look at a visual representation and analyze what is being done. That'll help you understand what is going on in the code.
2) Think about the run time (which is O(n^2) average case). Why is it O(n^2)? What does this mean?

Related

What is a one-pass algorithm, and is mine one?

For a class I'm taking, it is preferred to use a one-pass algorithm to fix a certain task. Since this class is outside of my specialization (I'm Built Environment, the class is Computer Science), and it isn't discussed in class, I haven't got a clue what a one-pass algorithm is. Googling it gave made me think something like this:
Each input can only be accessed once, and everything should be processed in order.
For my code below, this suggests to me that the for loop would fit in a one-pass algorithm, but I'm unsure about the while loop.
Could you tell me, preferably in layman's terms, what a one-pass algorithm means / entails, and if my code below fits this description?
public int[] computeDepth(int tree[]) {
int[] depth = new int[tree.length];
depth[0] = 0;
for (int index=1; index < tree.length; index++) {
depth[index] = 1;
int parentIndex = tree[index];
while (parentIndex != 0) {
parentIndex = tree[parentIndex];
depth[index]++;
}
}
return depth;
}
In computing, a one-pass algorithm is one which reads its input exactly once, in order, without unbounded buffering (you're not storing things elsewhere and counting that as one look). A one-pass algorithm generally requires O(n) (if you have n items, it takes n steps to finish) and less than O(n) storage (since you don't always need to use extra storage, it could be low as O(1)), where n is the size of the input.
(lifted straight from https://en.wikipedia.org/wiki/One-pass_algorithm, with some layman translation)
A for loop is a quintessential one-pass algorithm - you look at each value exactly once and move on. A while loop can work too, as long as it only looks at each value exactly once and does not repeat what the for loop looks at - but it's not in this case.
Your goal in this depth-first search is to look at each node exactly once, and move on, never repeating. The while loop traverses the tree multiple times, so no, it is not one-pass.
Hope that made sense.
In layman terms, a one-pass algorithm is one which reads its input exactly once, in order.
Does your code fits the description: No.
You are traversing the input tree multiple times with the inside while loop:
tree[index] and tree[parentIndex]
which violates the basic criteria for the one-pass algorithm.

How to find two number whose sum is given number in sorted array in O(n)?

public static void findNumber(int number) {
int[] soretedArray = { 1, 5, 6, 8, 9 };
for (int i = 0; i <= soretedArray.length; i++) {
for (int j = i + 1; j < soretedArray.length; j++) {
if (soretedArray[i] + soretedArray[j] == number) {
System.out.println(soretedArray[i] + "::" + soretedArray[j]);
return;
}
}
}
}
Using this code I am able to find the number and its complexity is O(N^2) but I have to find this using O(N) complexity i.e using only one for loop or hash-map or similar in Java.
I remember, I was watching the official Google video about this problem. Although it is not demonstrated in java, it is explained step-by-step in different variations of the problem. You should definitely check it:
How to: Work at Google — Example Coding/Engineering Interview
As explained in the Google video that Alexander G is linking to, use two array indexes. Initialize one to the first element (0) and the other to the last element (sortedArray.length - 1). In a loop, check the sum of the two elements at the two indexes. If the sum is the number you were looking for, you’re done. If it’s too high, you need to find a smaller number at one of the indexes; move the right index one step to the left (since the array is sorted, this is the right way). If on the other hand, the sum you got was too low, move the left index to the right to obtain a higher first addend. When the two indexes meet, if you still haven’t found the sum you were looking for, there isn’t any. At this point you have been n - 1 times through the loop, so the algorithm runs in O(n).
We ought to first check the precondition, that the array is really sorted. This too can be done in O(n), so doing it doesn’t break any requirements.
The algorithm may need refinement if you are required to find all possible pairs of numbers that yield the desired sum rather than just one pair.
Is this answer superfluous when the video link has already said it? For one thing, my explanation is shorter, so if it suffices, you’re fine. Most importantly, if the video is removed or just moved to another URL, my answer will still be here.
With fixed number, for any chosen x in the array you just have to find if number-x is in the array (Note that you can also bound x). This will not give you O(n), but O(n.log(n)).
Maybe by remarking that if you have a_i and a_j (j>i), taking the sum and comparing against number, if the result is greater next interesting tests are with a_(i-1) or a_(j-1), and if result is lower next interesting tests are with a_(i+1) or a_(j+1), will give hint to linear-time?

Very large Java ArrayList has slow traversal time

Solution: My ArrayList was filled with duplicates. I modified my code to filter these out, which reduced running times to about 1 second.
I am working on a algorithms project that requires me to look at large amounts of data.
My program has a potentially very large ArrayList (A) that has every element in it traversed. For each of these elements in (A), several other, calculated elements are added to another ArrayList (B). (B) will be much, much larger than (A).
Once my program has run through seven of these ArrayLists, the running time goes up to approximately 5 seconds. I'm trying to get that down to < 1 second, if possible.
I am open to different ways to traverse the ArrayList, as well as using a completely different data-structure. I don't care about the order of the values inside the lists, as long as I can go through all values, very fast. I have tried a linked-list and it was significantly slower.
Here is a snippet of code, to give you a better understanding. The code tries to find all single-digit permutations of a prime number.
public static Integer primeLoop(ArrayList current, int endVal, int size)
{
Integer compareVal = 0;
Integer currentVal = 0;
Integer tempVal = 0;
int currentSize = current.size()-1;
ArrayList next = new ArrayList();
for(int k = 0; k <= currentSize; k++)
{
currentVal = Integer.parseInt(current.get(k).toString());
for(int i = 1; i <= 5; i++)
{
for(int j = 0; j <= 9; j++)
{
compareVal = orderPrime(currentVal, endVal, i, j);
//System.out.println(compareVal);
if(!compareVal.equals(tempVal) && !currentVal.equals(compareVal))
{
tempVal = compareVal;
next.add(compareVal);
//System.out.println("Inserted: "+compareVal + " with parent: "+currentVal);
if(compareVal.equals(endVal))
{
System.out.println("Separation: " + size);
return -1;
}
}
}
}
}
size++;
//System.out.println(next);
primeLoop(next, endVal, size);
return -1;
}
*Edit: Removed unnecessary code from snippet above. Created a currSize variable that stops the program from having to call the size of (current) every time. Still no difference. Here is an idea of how the ArrayList grows:
2,
29,
249,
2293,
20727,
190819,
When something is slow, the typical advice is to profile it. This is generally wise, as it's often difficult to determine what's the cause of slowness, even for performance experts. Sometimes it's possible to pick out code that's likely to be a performance problem, but this is hit-or-miss. There are some likely things in this code, but it's hard to say for sure, since we don't have the code for the orderPrime() and primeLoop() methods.
That said, there's one thing that caught my eye. This line:
currentVal = Integer.parseInt(current.get(k).toString());
This gets an element from current, turns it into a string, parses it back to an int, and then boxes it into an Integer. Conversion to and from String is pretty expensive, and it allocates memory, so it puts pressure on garbage collection. Boxing primitive int values to Integer objects also allocates memory, contributing to GC pressure.
It's hard to say what the fix is, since you're using the raw type ArrayList for current. I surmise it might be ArrayList<Integer>, and if so, you could just replace this line with
currentVal = (Integer)current.get(k);
You should be using generics in order to avoid the cast. (But that doesn't affect performance, just the readability and type-safety of the code.)
If current doesn't contain Integer values, then it should. Whatever it contains should be converted to Integer beforehand, instead of putting conversions inside a loop.
After fixing this, you are still left with boxing/unboxing overhead. If performance is still a problem, you'll have to switch from ArrayList<Integer> to int[] because Java collections cannot contain primitives. This is inconvenient, since you'll have to implement your own list-like structure that simulates a variable-length array of int (or find a third party library that does this).
But even all of the above might not be enough to make your program run fast enough. I don't know what your algorithm is doing, but it looks like it's doing linear searching. There are a variety of ways to speed up searching. But another commenter suggested binary search, and you said it wasn't allowed, so it's not clear what can be done here.
Here is an idea of how the ArrayList grows: 2, 29, 249, 2293, 20727, 190819
Your next list grows too large, so it must contain duplicates:
190_819 entries for 100_000 numbers?
According to primes.utm.edu/howmany.html there are only 9,592 primes up to 100_000.
Getting rid of the duplicates will certainly improve your response times.
Why you have this line
current.iterator();
You don't use the iterator at all, you don't even have a variable for it. It's just waisting of time.
for(int k = 0; k <= current.size()-1; k++)
Instead of counting size every iteration, create value like:
int curSize = current.size() - 1;
And use it in loop.
It can save some time.

Adding 2 list element by element

I am having 2 Lists and want to add them element by element. Like that:
Is there an easier way and probably much more well performing way than using a for loop to iterate over the first list and add it to the result list?
I appreciate your answer!
Depends on what kind of list and what kind of for loop.
Iterating over the elements (rather than indices) would almost certainly be plenty fast enough.
On the other hand, iterating over indices and repeatedly getting the element by index could work rather poorly for certain types of lists (e.g. a linked list).
My understanding is that you have List1 and List2 and that you want to find the best performing way to find result[index] = List1[index] + list2[index]
My main suggestion is that before you start optimising for performance is to measure whether you need to optimise at all. You can iterate through the lists as you said, something like:
for(int i = 0; i < listSize; i++)
{
result[i] = List1[i] + List2[i];
}
In most cases this is fine. See NPE's answer for a description of where this might be expensive, i.e. a linked list. Also see this answer and note that each step of the for loop is doing a get - on an array it is done in 1 step, but in a linked list it is done in as many steps at it takes to iterate to the element in the list.
Assuming a standard array, this is O(n) and (depending on array size) will be done so quickly that it will hardly result in a blip on your performance profiling.
As a twist, since the operations are completely independent, that is result[0] = List1[0] + List2[0] is independent of result[1] = List1[1] + List2[1], etc, you can run these operations in parallel. E.g. you could run the first half of the calculations (<= List.Size / 2) on one thread and the other half (> List.Size / 2) on another thread and expect the elapsed time to roughly halve (assuming at least 2 free CPUs). Now, the best number of threads to use depends on the size of your data, the number of CPUs, other operations happening at the same time and is normally best decided by testing and modeling under different conditions. All this adds complexity to your program, so my main recommendation is to start simple, then measure and then decide whether you need to optimise.
Looping is inevitable except you have a matrix API (e.g. OpenGL). You could implement a List<Integer> which is backed by the original Lists:
public class CalcList implements List<Integer> {
private List<Integer> l1, l2;
#Override
public int get(int index) {
return l1.get(index) + l2.get(index);
}
}
This avoids copy operations and moves the calculations at the end of your stack:
CalcList<Integer> results1 = new CalcList(list, list1);
CalcList<Integer> results2 = new CalcList(results1, list3);
// no calculation or memory allocated until now.
for (int result : results2) {
// here happens the calculation, still without unnecessary memory
}
This could give an advantage if the compiler is able to translate it into:
for (int i = 0; i < list1.size; i++) {
int result = list1[i] + list2[i] + list3[i] + …;
}
But I doubt that. You have to run a benchmark for your specific use case to find out if this implementation has an advantage.
Java doesn't come with a map style function, so the the way of doing this kind of operation is using a for loop.
Even if you use some other construct, the looping will be done anyway. An alternative is using the GPU for computations but this is not a default Java feature.
Also using arrays should be faster than operating with linked lists.

Sliding an array in java - algorithm based

I'm writing a program in java where I need to slide the elements of the array and it should be performing as less as possible number of operations as it's inside a double loop and I'm working with length of array ranging from upto 10^8.
Example : A = {1,2,3,4,5,6}
Result : A = {2,3,4,5,6,1} for 1st time
A = {3,4,5,6,1,2} for 2nd time and so on..
Please feel free to suggest any other data structure or any modifications to the array!! Thank you guys!! :D
The simplest way to achieve that effect, is to do a "circular array"; that is, instead of moving the contents of the array, you can simply store the index that marks the beginning of the array.
To get the item at index i, you then do:
Type item = arr[(offset + i) % arr.length];
This way, you get the same properties as you have in an array, and you can perform any rotation in O(1).
In order to make this less of a hassle to use, you could make a simple wrapper class, that simply wraps an array, allowing easy rotation through this method. That way, the code could look clean, while you get efficient rotation.
In order to achieve an O(1) complexity, you could...
use a linked list
wrap your array with a class that stores the start position and let you access the array through "virtual" indexes (wrapped.acces(i) => array[(start + i) % array.length]
"double" your array and slice it in an appropriate way (so you don't have to change the surrounding code)
Otherwise, if you want to stick with your data structure, you need to pay O(n), no matter what.
I'd go with (2), because it is faster to both random access and linear access patterns (arrays have better data locality + O(1) random access complexity wrt O(n) of linked lists).
Use Collections.rotate(Arrays.asList(myArray), myDistance).
If you're not married to the idea of using arrays, then you could make use of the Collections.rotate() method.
List<Integer> list = new ArrayList<Integer>();
for (int i = 1; i <= 6; i++) {
list.add(i-1, new Integer(i));
}
int j = 0;
while (j < 100) {
Collections.rotate(list, -1);
System.out.print("{");
for (Integer integer : list) {
System.out.print(integer + ", ");
}
System.out.println("}");
}
Why do You have to rotate the table ?
Imagin that table is a circle and after that you can walk like this:
Object object = array[(offset + i) % array.length];
This give you O(1) on any access or rotation step;
You can use a simple List for that. If you do this sliding often, a queue would be the best choice.
The thing is, the array doesn't really change, you just start to read at position x and then continue to read at the start of the array length(array)-x elements. This is the fastest Variant.

Categories

Resources