I have a question regarding SelectionSort.
Please, take a look at my Code:
public static int[] sortiert(int[] array) {
for (int i = 0; i < array.length - 1; i++) {
for (int j = i + 1; j < array.length; j++) {
if (array[j] > array[i]) {
int speicher = array[i];
array[i] = array[j];
array[j] = speicher;
}
}
}
return array;
Can you please tell me why I have j = i + 1 in the second for-loop?
It bothers me...
array.length - 1 in the first loop is clear.
It would be nice to get an answer detailed
public static class SelectionSort
{
static int min;
public static void Sort(int[] data)
{
for (int i = 0; i < data.Length; i++)
{
for (int j = 0; j < data.Length; j++)
{
min = j;
if (data[i] < data[j])
Swap(x: ref data[i], y: ref data[min]);
}
}
}
private static void Swap(ref int x, ref int y)
{
x = x+y;
y = x-y;
x = x-y;
}
}
The sortiert method is running through the array multiple times. With every pair of elements, if the second element (the one later in the list) is greater than the first element (if (array[j] > array[i])), then it swaps the two elements, such that eventually the list will be sorted in decreasing order.
The i index represents the "first value" being compared above and the j index represents the "second value" being compared above. Thus, j will always start at i+1 as it must always be after the first value in the list. If j = i in the for loop, then you would be checking array[i] > array[i] because j = i in that case; since a number is never strictly less than itself, this would always return false and is thus an unnecessary operation.
Related
I don't understand the reason why the first for loop gives only one result, while the second gives me two results. Can someone explain to me how it works?
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] array = {5,5,11,15};
int target = 10;
System.out.print("First Solution: ");
twoSum(array,target);
System.out.println();
System.out.print("Second Solution: ");
twoSum2(array,target);
}
public static void twoSum(int[] array, int target){
for(int i = 0; i < array.length; i++){
for(int j = i+1; j < array.length; j++){
if(array[i] + array[j] == target){
System.out.print(Arrays.toString(new int[]{i, j}));
}
}
}
}
// if i want all the possible solutions
public static void twoSum2(int[] array, int target){
for(int i = 0; i < array.length; i++){
for(int j = 1; j < array.length; j++){
if(array[i] + array[j] == target){
System.out.print(Arrays.toString(new int[]{i, j}));
}
}
}
}
}
first output: [0, 1]
second output: [0, 1][1, 1]
Assumption
Your use case is to find pairs of elements in array that sum up to a target value
What's happening in twoSum() method or j = i + 1 case
As the inner loop starts with the immediately next index of the outer loop you are distinct pairs which are adding up to the desired value
What's happening in twoSum2() method or j = 1 case
As the inner loop starts with the index 1 every time regardless of the outer index value you are getting duplicate pairs which are adding up to the desired value along with an erroneous situation of a single element getting counted twice(I believe it's a bug and should be handled by an if condition check). Moreover, since it's starting from index 1 instead of 0 even all duplicates are not guaranteed. This approach should be avoided if my assumption of your use case is correct
Recommendation
Try exploring the Hashset based approach for this problem here. You can utilize the code or tweak it to match your use case. It's time complexity will be linear i.e. O(n) better than the current algorithm used in your code which is quadratic i.e. O(n^2)
The first finds all (i, j) such that j > i in approx. n*n/2 steps.
The second loop is probably long. If meant for (i, j) such that i ≠ j
public static void twoSum2(int[] array, int target) {
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length; j++){
if (j != i) {
if (array[i] + array[j] == target) {
System.out.print(Arrays.toString(new int[]{i, j}));
}
}
}
}
}
This excludes (0, 0), (1, 1), (2, 2), ...
However this takes approx. n² steps.
One could also take extend the first solution.
public static void twoSum2(int[] array, int target) {
for (int i = 0; i < array.length; i++) {
for (int j = i + 1; j < array.length; j++){
if (array[i] + array[j] == target) {
System.out.print(Arrays.toString(new int[]{i, j}));
System.out.print(Arrays.toString(new int[]{j, i}));
}
}
}
}
Tip: Arrays.sort may be used so you may start with largest fitting number. And Arrays.binarySearch to find target - array[i].
I need help counting the swaps and comparisons i na selected bubble sort algorithm. I have tried passing in values to change them for each iteration but I cannot figure out how I can successfully implement a counter for the swaps and comparisons.
static void bubbleSort(int[] userArray_Copy, int n, int swaps) {
swaps = 0;
int temp;
for (int i = 0; i < n; i++) {
for (int j = 0 ; j < n-1 ; j++) {
if (userArray_Copy[j] > userArray_Copy[j + 1]){
temp = userArray_Copy[j];
userArray_Copy[j] = userArray_Copy[j+1];
userArray_Copy[j+1] = temp;
swaps++;
}
}
}
}
How can I optimize my algorithm to find the minimum absolute value difference in a given array. Here is my approach which checks each and every element and returning the value.
static int minAbsVal(int[] myArray){
ArrayList<Integer> diffs= new ArrayList(); // all absolute value differences
for (int i = 0; i < myArray.length; i++) {
for (int j = 0; j < myArray.length; j++) {
if (myArray[j]!=myArray[i]){
int absVal =Math.abs( myArray[i]- myArray[j]);
diffs.add(absVal);
}
}
}
int min = diffs.get(0);
for (int i = 1; i < diffs.size(); i++) {
if (min>diffs.get(i)){
min = diffs.get(i);
}
}
return min;
}
Check this solution. If array contains duplicates than it returns 0 if you wanna avoid than you can add conditions also.
static int minAbsVal(int[] myArray){
Arrays.sort(myArray);
ArrayList<Integer> diffs= new ArrayList<Integer>(); // all absolute value differences
for (int i = 0; i < myArray.length-1; i++) {
diffs.add(Math.abs( myArray[i+1] - myArray[i]));
}
Collections.sort(diffs);
return diffs.get(0);
}
Or you can also use :-
static int minAbsVal(int[] myArray){
Arrays.sort(myArray);
int minimum=Math.abs( myArray[1] - myArray[0]);
for (int i = 1; i < myArray.length-1; i++) {
int diff = Math.abs( myArray[i+1] - myArray[i]);
if (diff == 0)
return 0;
else if (minimum > diff)
minimum = diff;
}
return minimum;
}
Check the following solution,
static int minimumAbsoluteDifference(int n, int[] arr) {
int a = Math.abs(arr[1]-arr[0]);
Arrays.sort(arr);
for(int x=0;x<n-1;x++){
if(Math.abs(arr[x]-arr[x+1])<a){
a = Math.abs(arr[x]-arr[x+1]);
if(a==0){
return a;
}
}
}
return a;
}
Dependson the size of your array a good approach would be to divide it in different smaller arrays and look for the minimum of each in pararell and then compare those results .
Anyways you dont need so many iterations, you can just set the baseValue to the first element of the array and when iterating the array compare the baseValue vs the current, if the current is smaller then asign baseValue to current (I would rename baseValue to minValue in that case)
So I have a problem, this method is supposed to sort an array of integers by using counting sort. The problem is that the resulting array has one extra element, zero. If the original array had a zero element (or several) it's fine, but if the original array didn't have any zero elements the result starts from zero anyway.
e.g. int input[] = { 2, 1, 4 }; result -> Sorted Array : [0, 1, 2, 4]
Why would this be happening?
public class CauntingSort {
public static int max(int[] A)
{
int maxValue = A[0];
for(int i = 0; i < A.length; i++)
if(maxValue < A[i])
maxValue = A[i];
return maxValue;
}
public static int[] createCountersArray(int[] A)
{
int maxValue = max(A) + 1;
int[] Result = new int[A.length + 1];
int[] Count = new int[maxValue];
for (int i = 0; i < A.length; i++) {
int x = Count[A[i]];
x++;
Count[A[i]] = x;
}
for (int i = 1; i < Count.length; i++) {
Count[i] = Count[i] + Count[i - 1];
}
for (int i = A.length -1; i >= 0; i--) {
int x = Count[A[i]];
Result[x] = A[i];
x--;
Count[A[i]] = x;
}
return Result;
}
}
You are using int[] Result = new int[A.length + 1]; which makes the array one position larger. But if you avoid it, you'll have an IndexOutOfBounds exception because you're supposed to do x-- before using x to access the array, so your code should change to something like:
public static int[] createCountersArray(int[] A)
{
int maxValue = max(A) + 1;
int[] Result = new int[A.length];
int[] Count = new int[maxValue];
for (int i = 0; i < A.length; i++) {
int x = Count[A[i]];
x++;
Count[A[i]] = x;
}
for (int i = 1; i < Count.length; i++) {
Count[i] = Count[i] + Count[i - 1];
}
for (int i = A.length -1; i >= 0; i--) {
int x = Count[A[i]];
x--;
Result[x] = A[i];
Count[A[i]] = x;
}
return Result;
}
Here you go: tio.run
int maxValue = max(A) + 1;
Returns the highest value of A + 1, so your new array with new int[maxValue] will be of size = 5;
The array Result is of the lenght A.lenght + 1, that is 4 + 1 = 5;
The first 0 is a predefinied value of int if it is a ? extends Object it would be null.
The leading 0 in your result is the initial value assigned to that element when the array is instantiated. That initial value is never modified because your loop that fills the result writes only to elements that correspond to a positive number of cumulative counts.
For example, consider sorting a one-element array. The Count for that element will be 1, so you will write the element's value at index 1 of the result array, leaving index 0 untouched.
Basically, then, this is an off-by-one error. You could fix it by changing
Result[x] = A[i];
to
Result[x - 1] = A[i];
HOWEVER, part of the problem here is that the buggy part of the routine is difficult to follow or analyze (for a human). No doubt it is comparatively efficient; nevertheless, fast, broken code is not better than slow, working code. Here's an alternative that is easier to reason about:
int nextResult = 0;
for (int i = 0; i < Count.length; i++) {
for (int j = 0; j < Count[i]; j++) {
Result[nextResult] = i;
nextResult++;
}
}
Of course, you'll also want to avoid declaring the Result array larger than array A.
public class MyBubbleSort {
public static void bubbleSort(int[] a, int n) {
int i, j, temp;
for (i = 0; i <= (n-2); i++) {
for (j = i + 1; j <= (n-1); j++) {
if (a[j] < a[i]) {
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
}
}
It gives me a sorted array when I do a debug but I just wanted to be 100% sure.
You could tidy the code a bit:
Make it extend an interface Sort with a single method sort(int[] a, int n).
MyBubbleSort method should implement said interface and not be static.
int i and j should be declared inside the corresponding fordeclaration.
temp should be declared inside the inner if.
It is questionable if you need to pass in the length of the array as this is a property on the Java array type. The only time to pass the length would be if you intended to sort sub arrays.
You are doing a correct bubble sort ! In your "if" statement, you are correctly swapping two adjacent values if they are not well sorted. And this is the principle of the bubble sort: you repeat this process until your array is correctly sorted. https://www.youtube.com/watch?v=lyZQPjUT5B4
However you are doing strange things in your code ! As zapl said in the comments you don't need this "n" parameter as you can simply get you array's size in your method.
Also prefer using " < length ", " < length - 1 " instead of your <= which are, if you think well, more intuitive
public static void bubbleSort(int[] tab) {
int n = tab.length ;
for (int i = 0; i < n-1; i++) {
for (int j = i + 1; j < n ; j++) {
if (tab[j] < tab[i]) {
int temp = tab[i];
tab[i] = tab[j];
tab[j] = temp;
}
}
}
}