Java Selection Sort - java

I am having issues getting my sort to check every index. It skips the 3rd indices for j as in it goes i[0], j[2], to i[0], j[4] I don't know why it is doing that?. Also, I am having trouble with my numbers actually be swapped. Does anybody know where my error is?
static void selectionSort(int[] arr) {
final long startTime = System.nanoTime(); // starts timer
System.out.println("Selection Sort");
//************** Code For Sorting *****************//
//*************************************************//
int counter = 0;
int first = 0;
int second = 0;
// Copies unsorted array to new array
//int[] sorted = Arrays.copyOf(arr, arr.length);
// sorts unsorted array for comparison later on
//Arrays.sort(sorted);
// comparing the first index value to
// the rest of the values in the array
for (int i = 0; i < arr.length - 1; i++) {
int minIndex = i;
// representing the next index value
// to the original and comparing it
for (int j = 1; j < arr.length - 1; j++) {
int nextIndex = j;
if (arr[minIndex] < arr[nextIndex]) {
System.out.println("i: " + i);
System.out.println("j: " + j);
System.out.println("Checking next index");
}
if (arr[minIndex] > arr[nextIndex]) {
System.out.println("i: " + i);
System.out.println("j: " + j);
//counter = j; // getting array index
first = arr[minIndex];
second = arr[nextIndex];
minIndex = second;
arr[minIndex] = second;
System.out.println("first:" + first);
System.out.println("second:" + second);
System.out.println("minIndex:" + minIndex);
System.out.println("arr[minIndex]:" + arr[minIndex]);
System.out.println("Possible lowest unsorted value");
}
//Swap here
if (arr[arr.length - 1] == arr[j]) {
arr[0] = second;
arr[counter] = first;
counter = 0;
//minIndex= i+1;
}
}
for (int k = 0; k < arr.length; k++) {
System.out.print(arr[k] + ", ");
}
System.out.println();
}
}

The first mistake you've made is within your nested for loop. the starting index (j) for the inner loop should always start at i + 1 (one place ahead of the indexer i) for each iteration of the outer for loop not j = 1 as you've done.
Second, by having the condition j < arr.length-1 you'll always exclude the last element within the array.
change this:
for(int j = 1; j < arr.length-1; j++)
to this:
for(int j = i + 1; j < arr.length; j++)
Moving on, there seems to be several problems with your algorithm including your swap functionality so, let's start again.
Selection sort is an in-place comparison-based algorithm in which the array is divided into two parts, the sorted part at the left end and the unsorted part at the right end. Initially, the sorted part is empty and the unsorted part is the entire array.
The smallest element is selected from the unsorted array and swapped with the leftmost element, and that element becomes a part of the sorted array. This process continues moving unsorted array boundary by one element to the right.
with that in mind, now we can start the algorithm.
public static void selectionSort(int[] arr){
for(int i = 0; i < arr.length-1; i++){
int minIndex = i; // smallest element index
for(int j = i + 1; j < arr.length; j++){
if(arr[j] < arr[i]){ // find smallest element
if(arr[j] < arr[minIndex])
minIndex = j; // update smallest element index
}
}
if(i != minIndex){ // swap
int temp = arr[minIndex];
arr[minIndex] = arr[i];
arr[i] = temp;
}
}
// print the result
Arrays.stream(arr).forEach(System.out::println);
}
as a side note, Selection sort complexities are of Ο(N2), where N is the number of elements within the array.

The algorithm of the selection sort looks as follows:
public static void selectionSort(int[] arr) {
// iterate over all subsets of the array
// (0-last, 1-last, 2-last, 3-last, ...)
for (int i = 0; i < arr.length; i++) {
// assume the min is
// the first element
int min = arr[i];
// index of the
// min element
int min_i = i;
// check the elements
// after i to find
// the smallest
for (int j = i + 1; j < arr.length; j++) {
// if this element
// is less, then it
// is the new min
if (arr[j] < min) {
min = arr[j];
min_i = j;
}
}
// if min element is not
// equal to the current
// one, then swap them
if (i != min_i) {
int temp = arr[i];
arr[i] = arr[min_i];
arr[min_i] = temp;
}
}
}
public static void main(String[] args) {
int[] arr = {5, 34, 1, 15, 3, 8, 9, 2, 7, 6, 43, 4};
selectionSort(arr);
System.out.println(Arrays.toString(arr));
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 34, 43]
}

Related

While loop after 1st iteration is not updating array values

I am trying to code cyclic sort and following is my code.
public static void main(String[] args) {
int temp = 0;
int[] nums = new int[]{4,2,1,3};
for(int i=0; i<nums.length; i++){
while(nums[i]!=nums[nums[i]-1]){
// line#8
System.out.println(nums[i] + " " + nums[nums[i]-1]);
temp = nums[i];
nums[i] = nums[nums[i]-1];
nums[nums[i]-1] = temp;
}
}
for(int i:nums){
System.out.println(i);
}
}
After 1st iteration in while loop:
i=0, nums[] = {3,2,1,4}. But after 1st iteration in while loop, if nums[0]=3, then nums[nums[0]-1] = 1, which is not the case i.e. nums[nums[0]-1] = 4. Also, this code will run into infinite loop and elements 3 & 4 will keep swapping.
Could someone explain me why while loop is not interpreting nums[nums[0]-1] as 1?
TIA
I revised your code it will work. you should store nums[i] - 1 value before you change nums[i].
int temp = 0;
int[] nums = new int[]{4, 2, 1, 3, 6, 8, 5, 7};
for (int i = 0; i < nums.length; i++) {
while (nums[i] != nums[nums[i] - 1]) {
temp = nums[i];
int index = nums[i] - 1;
nums[i] = nums[nums[i] - 1];
nums[index] = temp;
}
}
for (int i : nums) {
System.out.println(i);
}

HackerRank closest number

Given a list of unsorted integers, find the pair of elements that have the smallest absolute difference between them. If there are multiple pairs, find them all.
My reasoning was to compare each: arr[j] - arr[i] with lowest and if it is smaller or equal to that, add that value to the array lowest, but it's not working.
Code:
static int[] closestNumbers(int[] arr) {
int lowest = arr[1] - arr[0];
int lowestArray[] = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (Math.abs(arr[j] - arr[i]) < lowest) {
lowest = Math.abs(arr[j] - arr[i]);
}
}
}
for (int i = 0; i < arr.length; i++) {
if (arr[i] == lowest) {
lowestArray[i] = arr[i];
}
}
return lowestArray;
}
Below is the required code:-
import java.util.*;
class GFG
{
// Returns minimum difference between
// any two pair in arr[0..n-1]
static void printMinDiffPairs(int arr[], int n)
{
if (n <= 1)
return;
// Sort array elements
Arrays.sort(arr);
// Compare differences of adjacent
// pairs to find the minimum difference.
int minDiff = arr[1] - arr[0];
for (int i = 2; i < n; i++)
minDiff = Math.min(minDiff, arr[i] - arr[i-1]);
// Traverse array again and print all pairs
// with difference as minDiff.
for ( int i = 1; i < n; i++)
{
if ((arr[i] - arr[i-1]) == minDiff)
{
System.out.print("(" + arr[i-1] + ", "
+ arr[i] + ")," );
}
}
}
// Driver code
public static void main (String[] args)
{
int arr[] = {5, 3, 2, 4, 1};
int n = arr.length;
printMinDiffPairs(arr, n);
}
}
Does above program handle duplicates?
The cases like {x, x, x} are not handled by above program. For this case, the expected output (x, x), (x, x), (x, x), but above program prints (x, x), (x, x)
The problem is that when you initialize your lowest array like this,
int[] lowest = new int[arr.length];
you are actually initializing it with zeros. Also, whenever you are taking arr[j]-arr[i], it will always be greater than or equal to zero (since your array is sorted in an ascending fashion), leading to incorrect results because the following if statement,
if(Math.abs(arr[j] - arr[i]) <= lowest[l]) {
lowest[l] = Math.abs(arr[j] - arr[i]);
}
will never execute for differences greater than 0.
Initialize the lowest array like so,
for(int i=0;i<lowest.length;i++){
lowest[i] = Integer.MAX_VALUE;
}
Also, your outer loop for the i variable starts with i=1, but it should start with i=0
static int[] closestNumbers(int[] arr) {
int minAbs = Integer.MAX_VALUE;
Arrays.sort(arr);
int[] out = new int[(arr.length) + 3];
int j = 0;
for (int i = 1; i < arr.length; i++) {
minAbs = Math.min(minAbs, Math.abs(arr[i] - arr[i - 1]));
}
for (int i = 1; i < arr.length; i++) {
if(minAbs ==Math.abs(arr[i] - arr[i - 1])) {
out[j++]=arr[i - 1];
out[j++]=arr[i];
}
}
int[] tem= new int[j];
for(int i=0; i<j;i++) {
tem[i]=out[i];
}
return tem;
}

print highest number to the right in an array

I would like to have an optimized java program to print the highest digits to the right of an array.
For eg: a[]={3,6,7,2,4,1}
output should be 7,4,1.
I wrote a program like below
class Rightlargest{
public static void main(String args[]){
int a[]={1,3,2,4,5,2};
int c[]=new int[20];
for(int i=0;i<a.length;i++)
{
for(int j=i+1;j<a.length;j++)
{
if(a[i]<a[j]){
a[i]=a[j];
}
}
c[i]=a[i];
}
for(int i=0;i<c.length;i++)
{
if(c[i]!=c[i+1])
System.out.println(c[i]);
}
}
}
Even though I got the correct output, its throwing array out of bounds exception along with it.
Please advise.
When i equals of a.length-1, j takes value a.length and that is the problem.
The array has length of 5 elements. It means the last element has index of 4
Fix for : ArrayIndexOutOfBoundsException
i < c.length -1
for (int i = 0; i < c.length -1; i++) { // c.length -1
if (c[i] != c[i + 1])
System.out.println(c[i]);
}
This will not exceed the array index out of bounds. Your loop was executing 1 index more than array length.
As array length->20 and array index starts from 0, Your loop was iterating (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20) making last index to be checked as 21 which was out of array bounds.
Working code with fix:
public class RightLargest {
public static void main(String args[]) {
int a[] = { 1, 3, 2, 4, 5, 2 };
int c[] = new int[20];
for (int i = 0; i < a.length; i++) {
for (int j = i + 1; j < a.length; j++) {
if (a[i] < a[j]) {
a[i] = a[j];
}
}
c[i] = a[i];
}
for (int i = 0; i < c.length -1; i++) {
if (c[i] != c[i + 1])
System.out.println(c[i]);
}
}
}

How to count 1st duplicates value in array in Java

I have taken array int[] a = {33,33,5,5,9,8,9,9}; In this array so many values are duplicates means 33 comes twice & 5 also comes twice & 9 comes three times.
But I want to count the first value which is duplicate means 33 is first value which comes twice so answer would be 2.
I try:
public class FindFirstDuplicate
{
public static void main(String[] args) {
int c=0;
int[] a = {33,33,5,5,9,8,9,9};
outerloop:
for(int i = 0; i < a.length; i++)
{
for(int j = i+1; j< a.length; j++)
{
if(a[i] == a[j])
{
System.out.println(a[i]); //Duplicate value
c++;
break outerloop;
}
}
}
System.out.print("Count: "+c);
}
}
Output:
33
1
public class HelloWorld{
public static void main(String[] args) {
int[] a = {33,33,5,5,9,8,9,9};
for(int i = 0; i < a.length; i++)
{
int c=1; // we already found one.
// and we initialize this counter inside the loop,
// so that it is reset for each new starting number.
for(int j = i+1; j< a.length; j++) // we're starting from next number (reason we start with c=1)
{
if(a[i] == a[j])
c++;
}
if(c > 0) {
System.out.println("First uplicate value: "+ a[i] + " Count: " + c);
break; // we have to break out of the outer loop,
// so the inner loop can finish counting duplicates
}
}
}
}
Try something like:
int[] numbers = {33, 33, 5, 5, 9, 8, 9, 9};
Set<Integer> set = new HashSet<Integer>();
for (int i = 0; i< numbers.length; i++) {
if (!set.add(number[i])) {
System.out.println("first duplicate is " + number[i] + " and index is " + i);
break;
}
}
If the values in the array are non-negative and reasonably small, you can use a BitSet to store whether or not you have seen a value previously:
BitSet bits = new BitSet();
for (int i = 0; i < numbers.length; ++i) {
if (bits.get(numbers[i])) {
System.out.println("first duplicate at " + i + ": " + numbers[i]);
break;
}
bits.set(numbers[i]);
}
You could try this out:
int[] a = {33,33,5,5,9,8,9,9};
Integer[] uniques = new Integer[a.length];
Integer[] counts = new Integer[a.length];
int len = 0;
for(int num : a){
boolean matched = false;
for(int i = 0; i < len; i++){
if(num == uniques[i].intValue()){
matched = true;
counts[i] = new Integer(counts[i]+1);
break;
}
}
if(!matched){
uniques[len] = new Integer(num);
counts[i] = new Integer(1);
len++;
}
}
for(int i = 0; i < len; i++){
if(counts[i].intValue() > 1){
System.out.println("first duplicate is " + uniques[i] + " and number of times it appears " + counts[i]);
break;
}
}
In your code you exit both loops after the first duplicate is found, so any other occurences of the element would be ignored.
Also you start with c = 0. When you get to the second occurence, c will be incremented and be 1, not 2.
To count all elements simply change the loop condition of the outer loop and remove the break:
int c = 1;
int i;
for(i = 0; (c == 1) && (i < a.length); i++)
{
for(int j = i+1; j < a.length; j++)
{
if(a[i] == a[j])
{
c++;
}
}
}
System.out.println(a[i]); //Duplicate value
System.out.print("Count: "+c); // maybe do something else, if c == 1 (no duplicates)???
However SMA's answer describes a more performant way (for arbitrary input arrays) of finding the first duplicate. Once you found the second occurence of the first duplicate, you'd only need to count the number of occurences in the rest of the array to get the final count.

Return 0 or 1 from a method depending upon values in an array

I am a beginner. I am unable to figure out how to write a function which will return 1, if have this property:
arr[0] = arr[1] + arr[2] = arr[3] + arr[4] + arr[5] = arr[6] + arr[7] + arr[8] + arr[9] = ...
else returns 0. The length of an array must be n*(n+1)/2 for some n.
For example, if input array is {2, 1, 1, 4, -1, -1}, it returns 1 because 2 = 1 + 1, 2 = 4 + -1 + -1
I have tried this:
public static int myArray(int[] a) {
int len = a.length;
if (checkLenght(len)) {
int firstElem = a[0];
int value = 1;
int sum = 0;
for (int i = 1; i <= a.length; i++) {
for (int j = value; j < value + 1; j++) {
sum += a[j];
value++;
}
}
}
return 0;
}
public static boolean checkLenght(int len) {
for (int i = 0; i <= 100; i++) {
if ((i * (i + 1) / 2) == len) {
return true;
}
}
return false;
}
Thanks in advance.
I try to partition input in sets of two , three , .... elements. for that I use a pointer to show how many elements are in this partition. firs it is 2. then it is three , ... . and I use a temp number to count if in this partition I have enough element or not. after I have enough element in each partition I just check sum of the element of that partition.
This should do the work:
public static int myArray(int[] a) {
int len = a.length;
if (checkLenght(len)) {
int firstElem = a[0];
int pointer = 2; // pointer that will be 2, 3, 4 , ...
int sum = 0; // sum of element in each partition
int temp = 0; // a temp value to check if I reach desirable number of element in this partition or not.
for (int i = 1; i < a.length; i++) { // i<=a.length give you exception.
temp++;
sum += a[i];
if (temp == pointer) { // check if I have enough element.
pointer++; // plus pointer by one
temp = 0; // reset temp
if (sum != firstElem) // if in any of those partitions my needs doesnt meet I return zero.
return 0;
sum = 0; // reset sum
}
}
return 1;
}
return 0;
}

Categories