Insertion sort - Descending order - java

Sorry if its a basic question...
I am just trying to learn more on algorithms...
I wrote a simple code to perform insertion sort in ascending order, but for some reason I couldn't make it work to perform sort in descending order.
I tried changing the comparison key (while (i > 0 && a[i] > key) to (i > 0 && a[i] < key)).. it seems to work partially but the first element is not getting sorted, I get the below results..Can someone let me know where I am wrong?
1
11
10
9
5
4
3
2
public class InsertionSort {
public static void main(String args[]) {
int[] a = { 1,10,11,5, 9, 3, 2, 4 };
// Loop through the entire array length. Consider you already have one
// element in array, start comparing with
// first element
for (int j = 1; j < a.length; j++) {
// Get the key (The value that needs to be compared with existing
// values.
int key = a[j];
// Get the array index for comparison, we need to compare with all
// other elements in the array with
// key
int i = j - 1;
// While i > 0 and when key is less than the value in the array
// shift the value and insert
// the value appropriately.
//System.out.println(j);
while (i > 0 && a[i] < key) {
a[i + 1] = a[i];
i = i - 1;
a[i + 1] = key;
}
}
for (int k = 0; k < a.length; k++) {
System.out.println(a[k]);
}
}
}

You're never touching a[0] in
while (i > 0 && a[i] < key) {
so it isn't sorted into its due place. Use >= instead of >:
while (i >= 0 && a[i] < key) {
The same problem would occur when sorting in ascending order.

The first element in the array is a[0]. You're not comparing it anywhere.

Start from 0 with array a[] to reach the first element a[0]. So first element in a[j] will be a[0] and not a[1];

public static void insertionSort(int[] arr)
{
for (int i = 1; i < arr.length; i++)
{
int curNumber = arr[i];
int curIndex = i-1;
while ( curIndex >= 0 && arr[curIndex] < curNumber)
{
arr[curIndex+1] = arr[curIndex];
curIndex--;
}
arr[curIndex+1] = curNumber;
}
}

Related

What is the issue with my maximum product algorithm

Here is the code:
public static int MaxProduct(int... a){ // the max possible product from an array
int i = 0;
int j = 0;
int m = 0;
int n = a.length;
while (i<n){
j++;
while(j<n ){
if (a[i]*a[j] > m){
m = a[i]*a[j];
j++;
}
}
i++;
}
return m;
}
System.out.println(MaxProduct(1,2,3,4,5));
The algorithm seems to work as expected (after check and making a table of the debugger). For the first index of an array it checks all possible products and edits m accordingly from 1 through to 5. And then once j is equal to 5 a[j]understandably is out of bounds since there are only 5 elements in the array
I then see the arrayoutofbounds error in the debugger beside (again which is what id expect) but instead of i increasing, and the second while loop starting the cycle again, a[i] stays as 1, the algorithm concludes, and i get the output 5
How do i get this to output 20 (4x5)
You need to make two changes. Check below 2 TODOs.
public static int MaxProduct(int... a) { // the max possible product from an array
int i = 0;
int j = 0;
int m = 0;
int n = a.length;
while (i < n) {
j = i + 1; // TODO: 1
while (j < n) {
if (a[i] * a[j] > m) {
m = a[i] * a[j];
}
j++; // TODO:2
}
i++;
}
return m;
}

Given two sorted lists (or arrays) and a number k, create an algorithm to fetch the least k numbers of the two lists

Need to find the first 3 smallest number in given two sorted array. I supposed that two array should merge into one first and sort it in order to fetch the first 3 smallest number. Can anyone help me with the merge and sort part or provide some advice, any help will appreciate.
This is where i reached now, I only can get the smallest number ( not first 3, just one).
public class MergeandSort {
public static void main(String[] args) {
int[] set1 = {1,2,6,9,18};
int[] set2 = {2,3,7,10,21,30};
int smallest = set1[0];
int smallests = set2[0];
for(int i=0; i < set1.length; i++){
if(set1[i] < smallest)
smallest = set1[i];
}
for(int k=0; k < set2.length; k++){
if(set2[k] < smallests)
smallests = set2[k];
}
System.out.println("Smallest Number in Set 1 is : " + smallest);
System.out.println("Smallest Number in Set 2 is : " + smallests);
}
}
The arrays are already sorted, so you don't have to iterate over the entire arrays to find the 3 smallest numbers.
You just have to start iterating over both arrays at the same time (i.e. in the same loop).
In each iteration you compare the current two elements of the two arrays (starting at the 2 elements at the 0 index) and take the smaller of them
Then you advance the index of the array from which you took the smallest number.
Once you reach 3 elements (after 3 iterations), you break out of the loop.
Here's some pseudo code to get you started:
int i = 0;
int j = 0;
int c = 0;
int[] lowest3 = new int[3];
while (true) {
find the smaller of set1[i] and set2[j] and put it in lowest3[c]
if set1[i] is smaller, increment i
otherwise increment j
increment c
if (c==3) // you are done
break;
}
the lowest3 array now contains the 3 lowest numbers of both arrays
Of course you can swap 3 with any k. You just have to make sure that i is always smaller than set1.length and j is always smaller than set2.length.
If the arrays are already sorted, just implement the merging technique of merge sort with the limitation in while condition that it should run only k times (in this case 3), but dont forget to check that size of sets are less than k or not!
int k = 0,i = 0,j = 0;
while (k<3 && k<set1.length && k<set2.length )
{
if (set1[i] <= set2[j])
{
final_set[k] = set1[i];
i++;
}
else
{
final_set[k] = set2[j];
j++;
}
k++;
}
while (k<3 && k<set1.length) {
final_set[k]=set1[i];
k++;
i++;
}
while (k<3 && k<set2.length) {
final_set[k]=set1[j];
k++;
j++;
}
public class MergeandSort {
public static void main(String[] args) {
int[] set1 = {1,2,6,9,18};
int[] set2 = {2,3,7,10,21,30};
int[] sorted = new int[k];
int smallest = set1[0];
int smallests = set2[0];
int i = 0, j = 0, c = 0;
while(i < set1.length && j < set2.length && c < k){
if (set1[i] < set2[j])
sorted[c++] = arr1[i++];
else
sorted[c++] = arr2[j++];
while (i < set1.length && c < k)
sorted[c++] = arr1[i++];
while (j < set2.length && c < k)
sorted[c++] = arr2[j++];
System.out.println(sorted);
}
}
where k is the count of sorted numbers you want
That would not work as:
Array1 = {1,3,5}
Array2 = {2,3,4}
Correct solution: {1,2,3}
Output of your solution: {1,3,4}

Java Insertion Sort - copying values down array

I need to make this insertion sort function essentially copy elements to the right until the value that needs to be moved would be in the correct position, however, with the code I'm using I typically end up getting garbage out, and have tried multiple iterations with the same result. I am at wits end as I see no reason why this shouldn't work.
public static void Sort(Comparable[] a) {
int n = a.length;
Comparable temp = 0;
int x;
// Starting with the element at index 1...
for (int i = 1; i < n; i++) {
// ...move to the left until we find one less
// than the current element.
for (int j = i; j > 0; j--) {
if (less(a[j], a[j - 1]))
{
temp = a[j];
for(x = j; x > 0 && less(temp, a[x]); x--)
{
a[x] = a[x - 1];
}
a[x] = temp;
//exch(a, j, j - 1);
}
else
break;
}
}
}
less(a, b) checks to see if a < b, by the way.
On the first iteration of the innermost loop, in this condition: x > 0 && less(temp, a[x]) you are checking whether the value you just stored in temp... is less than the value you just stored in temp, referred to by another name. This will always return false, causing the loop to never start. The end result is that the entire method is an expensive no-op. If you're testing it by sending in a randomly jumbled array, you'll end up with the array still randomly jumbled when it's done.
To fix this, simply subtract 1 from the index in that condition, making it x > 0 && less(temp, a[x - 1]).
The rest of your code looks correct, I think, though the loop with j is redundant and can be removed.
This should do the trick
public static void Sort(Comparable[] a) {
int n = a.length;
Comparable temp = 0;
int x;
// Starting with the element at index 1...
for (int i = 1; i < n; i++) {
// ...move to the left until we find one less
// than the current element.
for (int j = i; j > 0; j--) {
if (less(a[j], a[j - 1]))
{
temp = a[j];
for(x = j; x > 0 && less(temp, a[x-1]); x--)
{
a[x] = a[x - 1];
}
a[x] = temp;
//exch(a, j, j - 1);
}
else
break;
}
}
}

How to reverse the all element of ArrayList using reverse method?

I have to make a method that can reverse all elements of ArrayList ...
For exmaple,
if my list have <12 1 34 56 43> elements. then it should reverse the whole list.
<43 56 34 1 12>.
I've tried this method, but it doesn't work. Here is the method
public void reverse() {
int size=0;
for (int i = 0, j = size - 1; i < size && j >= 0; i++, j--)
{
int temp = j;
j = i;
i = temp;
}
}
when I call this method list.revese(). it doesn't reverse the list.
Can anyone please help me out!!!
Your code deals with the index but not the actual element of the index. Also note that if j < i, you are doing the reversing twice, thus there will be no effect.
public void reverse(List<Integer> list) {
int size=list.size();
for (int i = 0, j = size - 1; i < size && j >= 0 && i <= j; /** i must be smaller. */ i++, j--)
{
int temp = list.get(j);
list.set(j, list.get(i));
list.set(i,temp);
}
}
Use the ArrayList object, and then after building your array you can just run the following to reverse the contents:
Collections.reverse(your ArrayList Here);
Initialize 'size' variable to the length of the ArrayList. You are initializing it to 0.

how to find the sum of two elements in an array closest to zero

How to find two elements from an array whose sum is closest to zero but not zero(note: -1 is closest to zero than +2).I tried this...
int a[]=new int[n];
int b[]=new int[2];
int prev=0;
for(int i=0;i<n;a[i++]=in.nextInt());
for(int i=0;i<a.length;i++){
for(int j=i+1;j<a.length;j++){
int sum=a[i]+a[j];
if(prev==0)
prev=sum;
if(sum > 0){
if(sum < prev ){
prev=sum;
b[0]=a[i];
b[1]=a[j];
}
}
else if(sum < 0){
if(-sum < prev){
prev=sum;
b[0]=a[i];
b[1]=a[j];
}
}
}
}
Sop(b[0]+" "+b[1]);
I have a few remarks, you are using 3 for loops, which can be improved to just 2 nested for loops (the outer loop for selecting the current element and the inner loop to compare with the other elements).
Also you have multiple if tests to check if the sum is now closer to zero then the previous sum. However these if tests can be reduced to just one if test, by taking the absolute value of the sum instead of testing on sum > 0 and sum < 0, which is fine for the readability.
This is what i came up with :
int array[] = new int[5];
array[0] = -3; array[1] = -2; array[2] = -1; array[3] = 1; array[4] = 2; // Fill array
int idx[] = new int[2]; // Will store the result (index of the two elements that need to be added)
double lowest_sum = Double.POSITIVE_INFINITY; // Of type double to be able to use infinity
for(int i = 0; i < array.length; i++) {
// Outer loop --> Uses a current (array[i]) from left to right
int current = array[i];
for(int j = i+1; j < array.length; j++) {
// Inner loop --> Check all elements we didn't used as current till now
int compare_with = array[j];
if((Math.abs(current + compare_with) < lowest_sum) && ((current + compare_with) != 0)) {
// We found two elements whose sum is closer to zero
lowest_sum = Math.abs(current + compare_with);
idx[0] = i; // Index of the first element to add
idx[1] = j; // Index of second element to add
}
}
}
int res_idx1 = idx[0];
int res_idx2 = idx[1];
System.out.println("The first element to add is : " + array[res_idx1] + "\nThe second element to add is : " + array[res_idx2]);
Input : array = [-3, -2, -1, 1, 2] , Output : The first element to add is : -3,
The second element to add is : 2
Note that this code will print a solution and not all solutions (if multiple solutions exists). It should be fairly trivial to edit the code such that it returns all solutions.
you can try:
int a[]=new int[n];
int b[]=new int[2];
int prev=0;
for(int i=0;i<n;a[i++]=in.nextInt());
for(int i=0;i<a.length;i++){
for(int j=i+1;j<a.length;j++){
int sum=a[i]+a[j];
if(prev==0)
prev=sum;
if(Math.abs(sum)>0 && Math.abs(sum)<Math.abs(prev)){
prev=sum;
b[0]=a[i];
b[1]=a[j];
}
}
}
Sop(b[0]+" "+b[1]);
This problem can be solved in O(N*log(N)). The most expensive operation in this case will be sorting your array. If your domain allows you to use non-comparative sorts, such as counting sort then you'll be able to reduce time complexity of the whole solution to linear time.
The idea is that in sorted array, you can iterate elements in ascending and descending order in parallel and thus find all pairs with minimal/maximal sum in linear time. The only disadvantage of such approach in application to your task is that you need to find minimal absolute value of the sum, that means finding minimum among positive sums and maximum among negative sums. This will require two linear passes.
My solution is below. It is verified on randomized data against the bruteforce O(N^2) solution.
// note: mutates argument!
static Solution solve(int a[]) {
Arrays.sort(a);
int i = 0;
int j = a.length - 1;
// -1 indicates uninitialized min value
int minI = -1;
int minJ = -1;
int min = 0;
// finding maximal sum among negative sums
while (i < j) {
int cur = a[i] + a[j];
if (cur != 0 && (minI == -1 || Math.abs(cur) < Math.abs(min))) {
min = cur;
minI = i;
minJ = j;
}
// if current sum is below zero, increase it
// by trying the next, larger element
if (cur < 0) {
i++;
} else { // sum is already non-negative, move to the next element
j --;
}
}
i = 0;
j = a.length - 1;
// finding minimal sum among positive sums
while (i < j) {
int cur = a[i] + a[j];
if (cur != 0 && (minI == -1 || Math.abs(cur) < Math.abs(min))) {
min = cur;
minI = i;
minJ = j;
}
if (cur > 0) {
j--;
} else {
i ++;
}
}
if (minI >=0) {
return new Solution(minI, minJ, min);
//System.out.printf("a[%d]=%d, a[%d]=%d, sum=%d", minI, minJ, a[minI], a[minJ], min);
} else {
return null;
//System.out.println("No solution");
}
}
I just realized that sorting messes the indices, so minI and minJ will not correspond to the indices in the original non-sorted array. The fix is simple — original array should be converted to the array of pairs (value, original_index) before sort. Though I will not implement this fix in my example snippet, as it will further affect readability.

Categories