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;
}
}
}
}
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 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.
This question already has answers here:
How to get unique values from array
(13 answers)
Closed 8 years ago.
void RemoveDups(){
int f=0;
for(int i=1;i<nelems;i++){
if(arr[f]==arr[i]){
for(int k=i;k<nelems;k++)
{
arr[k]=arr[k+1];
}
nelems--;
}
if(i==(nelems+1)){
f++;
i=f+1; //increment again
}
}
}
This is the logic i have written to remove duplicate elements from an array ,but this is not working at all ?what changes i should make to make it work? or you people have better logic for doing the same considering time complexity.and i don't want to use built-in methods to achieve this.
int end = input.length;
for (int i = 0; i < end; i++) {
for (int j = i + 1; j < end; j++) {
if (input[i] == input[j]) {
int shiftLeft = j;
for (int k = j + 1; k < end; k++, shiftLeft++) {
input[shiftLeft] = input[k];
}
end--;
j--;
}
}
}
I think you can use Set Collection
copy all the values to an HashSet and then using Iterator access the Values
Set<Integer> hashset= new HashSet<Integer>();
You have two options, C# has the Distinct() Linq expression that will do this for you (Missed the Java tag), however if you need to remove items, have you thought about sorting the list first, then comparing the current item to the previous item and if they're the same, remove them. It would mean your diplicate detection is only ever running through the array once.
If you're worried about sort you could easily implement an efficient bubble sort or somthing to that effect
You never decrease i after You compared for examlpe arr[0] to arr[5], You never will test arr[1] == arr[2]
You need to start a new loop (i) after You've incremented f.
try
for(int f=0;f<nelems-1;f++)
{
for(int i=f+1;i<nelems;i++)
{
...
}
}
with this nested for loop you can compare every two element of the array.
a good start is to eliminate duplicate elements without shrinking the array which is done lastly:
public class run2 extends Thread {
public static void main(String[] args) {
int arr[] = { 1, 2, 2, 3, 5, 6, 5, 5, 6, 7 };
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] == -1)
j++;
if (arr[i] == arr[j])
arr[j] = -1;
}
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + ",");
}
System.out.println();
for (int i = 0; i < arr.length; i++) {
if (arr[i] == -1) {
for (int j = i; j < arr.length; j++) {
if (arr[j] != -1) {
arr[i] = arr[j];
arr[j] = -1;
break;
}
}
}
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + ",");
}
}
}
Adapt this code :
public static int[] removeDuplicates(int[] numbersWithDuplicates) {
// Sorting array to bring duplicates together
Arrays.sort(numbersWithDuplicates);
int[] result = new int[numbersWithDuplicates.length];
int previous = numbersWithDuplicates[0];
result[0] = previous;
for (int i = 1; i < numbersWithDuplicates.length; i++) {
int ch = numbersWithDuplicates[i];
if (previous != ch) {
result[i] = ch;
}
previous = ch;
}
return result;
}
As far as I understood from your code,you are comparing each value starting from index 0 to the rest of the element and when you see the element which is located at index f your are trying to shift the entire array and decrementing the size of array(nelems).Look at line no. 11
if(i==(nelems+1)){
f++;
i=f+1;
The problem is when i is set to f+1,i will again be incremented in the for loop for the next iteration.So basically i starts comparing from f+2.And also you are comparing i with (nelems+1) considering the case when nelems decremented but you are not considering the case when i reaches the end without decreasing nelems in that case i will never be equale to (nelems+1).Now considering your logic you could do 2 things.
1.Here is your working code.
for(int i=1;i<nelems;i++){
if(arr[f]==arr[i]){
for(int k=i+1;k<nelems;k++)
{
arr[k-1]=arr[k];
}
if(i==(nelems-1)){
f++;
i=f;
}
nelems--;
}
if(i==(nelems-1)){//end of the loop
f++;
i=f; //increment again
}
}
2.You could use an outer for loop alternatively that will increment the f value once the inner for is completed.
void RemoveDups(){
for(int f=0;f<nelems;++f){
for(int i=1;i<nelems;i++){
if(arr[f]==arr[i]){
for(int k=i;k<nelems;k++)
arr[k]=arr[k+1];
nelems--;
}
}
}
}
Now your problem is solved but the time complexity of your code will be(O(N^3)).
Now instead of shifting the entire array at line 4,you could just swap the arr[f] with last element.
if(arr[f]==arr[i]){
swap(arr[f],arr[nelems-1]);
nelems--;
}
it will reduce the time complexity from O(N^3) to O(N^2).
Now I'll suggest you my method
1.just sort the array.It will be done in O(NlogN).
2.now using one for loop you can get what do you wanted.
void RemoveDups(){
int k=0,i;
for(i=1;i<nelems;++i){
while(arr[i]==arr[i-1])
++i;
arr[k++]=arr[i-1];
}
arr[k++]=arr[i-1];
}
Now basically you got an array of size k,which contains non repeated element in sorted order and the time complexity of my solution is O(NlogN).
This question already has answers here:
bubble sort with a boolean to determine whether array is already sorted
(3 answers)
Closed 8 years ago.
I have two implementations of bubble sort, but one of them works fine and other one does not can anybody explain me what is the difference in these two
first one this works fine
private static int[] sortBuble(int[] a) {
boolean swapped = true;
for (int i = 0; i < a.length && swapped; i++) {
swapped = false;
System.out.println("number of iteration" + i);
for (int j = 1; j < a.length; j++) {
if (a[j - 1] > a[j]) {
int temp = a[j - 1];
a[j - 1] = a[j];
a[j] = temp;
swapped = true;
}
}
}
return a;
}
Second one this does not work, but they look more or less same
private static int[] sortBuble1(int[] a) {
boolean swapped = true;
for (int i = 0; i < a.length && swapped; i++) {
swapped = false;
System.out.println("number of iteration" + i);
for (int j = i + 1; j < a.length; j++) {
if (a[i] > a[j]) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
swapped = true;
}
}
}
return a;
}
They are not the same. You are holding i constant for each iteration of the inner-for loop in the second example, and using a[i] for comparison, which is just incorrect. As I said in my other answer, the first is also inefficient. The following is an optimized version of the first one:
private static int[] bubblesort(int[] nums)
{
boolean done = false;
for (int i = 0; i < nums.length && !done; i++)
{
done = true;
for (int j = nums.length-1; j > i; j--)
{
if (nums[j] < nums[j-1])
{
int temp = nums[j];
nums[j] = nums[j-1];
nums[j-1] = temp;
done = false;
}
}
}
return nums;
}
At the end of the ith iteration, we know that the first i elements are sorted, so we don't need to look at them anymore. We need the boolean to determine if we need to continue or not. If no swaps are made, then we are done. We can remove the boolean and it will still work, but will be less efficient.
The difference lies in the indexes used for the arrays.
In the first case, your inner for loop with j is independent of i. Also, you use adjacent values of j while swapping, so that you are always swapping adjacent values in the array.
In the second case, your inner for loop starts j from i + 1. And you're using both i and j to index your array. So you're actually not comparing adjacent elements, but elements that may be far apart (e.g., when i=1 and j=4). That is not bubble sort, and this algorithm will not work that way.
I have a homework assignment to sort an array in ascending order. Obviously, this is to be done manually without using any kind of sort() function.
I figured to do it, I would need two for loops: the first one will loop through the existing array and create a temporary value with the value and index of the array. The second loop will compare the temporary values to the existing values and sort them. I keep trying to write the code, but I just can’t seem to get it right. Here is the latest method I came up with:
public int[] sortArray (int[] inArray)
{
//Construct the array we're using here
int[] newArray = inArray;
for(int x = 0; x < a.length; x++) //a.length = # of indices in the array
{
int tempValue = a[x];
int tempIndex = x;
for(int y = 0; y < a.length; y++)
{
if(tempValue < a[y])
{
newArray[x] = tempValue;
}
}
}
return newArray;
}
I’m pretty sure this is incorrect, but if someone could push me in the right direction it would be very appreciated!
You have a nearly OK version of the Selection Sorter. You need to start your y at x+1, not at 0. Otherwise you're re-scanning the sorted portion of the array. You should also note that selection sort is an in-place algorithm; if you are looking to make a copy of the array, you should use Arrays.copy method, otherwise int[] newArray = inArray;
is creating an alias, not a copy. Finally, the if statement in the nested loop should swap a[x] and a[y], not simply put tempValue in:
if(newArray[x] < newArray [y]) {
int tempValue = newArray[y];
newArray[y] = newArray[x];
newArray[x] = tempValue;
}
Instead of trying to invent your own sorting algorithm, I'd urge you to study what already exists. There's a ton of prior art on this.
Take a look at the Wikipedia article: Sorting algorithm.
Bubble sort is very easy to implement, but has quadratic complexity (the same as your current attempt).
Quicksort isn't too hard to implement either, and has better average complexity.
int minval = input[0];
int temp=0;
for(int i = 0; i< input.length; i++)
{
for(int j = 0; j< input.length-1; j++)
{
if(input[j+1]<input[j])
{
temp=input[j+1];
input[j+1]=input[j];
input[j]=temp;
}
}
}
The sorting you are trying to achieve is called Bubble sort - the wikipedia entry is pretty good you should read it. Though, it's never really used because there is better alternative - Insertion sort (An example is Timsort in Python which is a hybrid of Merge sort and Insertion sort). These two are the basic algorithms that fits your idea with two loops, hence O(n2) complexity.
You should also consider different algorithms for your assignment or, at least, be aware of:
Merge sort
Quicksort
Hope it helps.
int arr[] = new int[]{10, 20, 5, 6, 30, 1, 2};
boolean bool = true;
int t = 0;
while (bool) {
for (int i = 0; i < arr.length - 1; i++) {
if (arr[i] > arr[i + 1]) {
int c = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = c;
t++;
}
}
if (t == 0) {
bool = false;
}
t = 0;
}
for (int y : arr) {
System.out.println(y);
}
int[] number = { 1,2,1,3,5,4 };
int temp;
for (int i = 0; i < number.length; i++)
{
for (int j = i + 1; j < number.length; j++)
{
if (number[i] > number[j])
{
temp = number[i];
number[i] = number[j];
number[j] = temp;
}
}
}
for (int i = 0; i <number.length; ++i)
System.out.println(number[i]);
}