Okay, I am out of touch from these school theories but i am trying to refresh myself. I read the algorithm and implemented it. Here is the code
public int[] bubbleSort(int[] array)
{
int swap_bucket;
for (int i = 0; i < array.length; i++)
{
for (int j = i + 1; j < array.length; j++)
{
if (array[i] > array[j])
{
swap_bucket = array[i];
array[i] = array[j];
array[j] = swap_bucket;
}
}
}
return array;
}
And here is InsertionSort
public int[] InsertionSort(int array[])
{
int swap_bucket;
for (int i = 0; i < array.length; i++)
{
for (int k = i; ((k > 0) && (array[k] < array[k-1])); k--)
{
swap_bucket = array[k];
array[k] = array[k-1];
array[k-1] = swap_bucket;
}
}
return array;
}
To me, both looks same. I am comparing each element and the moment I find it, I swap it.. but it looks like both implementations are more or less same. Did I code it wrong?
Yes, In my opinion you coded Insertion sort wrong.
Check the implementation on Insertion Sort
Bubble Sort: In Bubble sort In an iteration we compare the element with all other elements and if condition( < or > ) is true then we swap the element
whereas
Insertion Sort: In an iteration in Insertion sort we compare the element in focus with other elements and place it at its correct location in the sorted part of the array.
Hint: Looking into both the algorithms and seeing when the swap is being done will help you understand the difference better.
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 can't wrap my head around this. Need to find duplicates and I did. All now that is left is to print how many times a duplicate appears in the array. I just started with Java,so this needs to be hard coded for me to understand. Spend last two days trying to figure it out but with no luck.. Any help will be great! Talk is cheap,here is the code..
import java.util.Arrays;
public class LoopTest {
public static void main(String[] args) {
int[] array = {12,23,-22,0,43,545,-4,-55,43,12,0,-999,-87};
int positive_counter = 0;
int negative_counter = 0;
for (int i = 0; i < array.length; i++) {
if(array[i] > 0) {
positive_counter++;
} else if(array[i] < 0) {
negative_counter++;
}
}
int[] positive_array = new int[positive_counter];
int[] negative_array = new int[negative_counter];
positive_counter = 0;
negative_counter = 0;
for (int i = 0; i < array.length; i++) {
if(array[i] > 0) {
positive_array[positive_counter++] = array[i];
} else if(array[i] < 0) {
negative_array[negative_counter++] = array[i];
}
}
System.out.println("Positive array: " + (Arrays.toString(positive_array)));
System.out.println("Negative array: " + (Arrays.toString(negative_array)));
Arrays.sort(array);
System.out.println("Array duplicates: ");
for (int i = 0; i < array.length; i++) {
for (int j = i + 1; j < array.length; j++) {
if(array[i] == array[j]) {
System.out.println(array[j]);
}
}
}
}
}
Since you are already sorting the array you can find the duplicates with just one loop (they will be next to each other right?). So you can do something like:
Arrays.sort(array);
System.out.println("Array duplicates: ");
int lastValueCount=1; //How many times we met the current value (at least 1 - this time)
for (int i = 1; i < array.length; i++){
if(array[i] == array[i-1])
lastValueCount++; //If it is the same as the previous increase the count
else {
if(lastValueCount>1) //If it is duplicate print it
System.out.println(array[i-1]+" was found "+lastValueCount+" times");
lastValueCount=1; //reset the counter
}
}
Result for your array is:
Array duplicates:
0 was found 2 times
12 was found 2 times
43 was found 2 times
Also you can use some of the Java bells and whistles like inserting the values into Map or something like that but I guess you are looking from an algorithmic point of view so the above is the simple answer with just one loop
Just go through your solution, first you separate positive and negative numbers in two different arrays, then you never use them, so what's the purpose of this separation ?
I am giving you just an idea related to your problem, it's better to solve it by your self so that you can get hands on Java.
Solution: you can use Dictionary-key value pair. Go through your array, put element in dictionary as a key and value as zero, on every iteration check if that key already exist in Dictionary, just increment its value. In the end, all of the values are duplicates that occurs in your array.
Hope it helps you.
From the algorithmic point of view, Veselin Davidov's answer is good (the most efficient).
In a production code, you would rather write it like this :
Map<Integer, Long> result =
Arrays.stream(array)
.boxed() //converts IntStream to Stream<Int>
.collect(Collectors.groupingBy(i -> i, Collectors.counting()));
The result is this Map :
System.out.println(result);
{0=2, 545=1, -4=1, -22=1, -87=1, -999=1, -55=1, 23=1, 43=2, 12=2}
An easy way would be using Maps. Without changing code too much:
for (int i = 0; i < array.length; i++) {
int count = 0;
for (int j = i + 1; j < array.length; j++) {
if(array[i] == array[j]) {
System.out.println(array[j]);
count++;
}
}
map.put(array[i], count);
}
Docs:
https://docs.oracle.com/javase/7/docs/api/java/util/Map.html
Edit: As a recommendation, after you are done with the example, you should analize your code and find what isn´t neccesary, what could be done better, etc.
Are all your auxiliary arrays neccesary? Are all loops necessary?
You can do it by creating an array list for duplicate values:-
Arrays.sort(array);
System.out.println("Array duplicates: ");
ArrayList<Integer> duplicates = new ArrayList<Integer>();
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length; j++) {
if(j != i && array[i] == array[j] && !duplicates.contains(array[i])){
duplicates.add(array[i]);
System.Out.println(duplicates[duplicates.size()-1]);
}
}
}
public static void findDuplicate(String s){
char[] charArray=s.toCharArray();
ArrayList<Character> duplicateList = new ArrayList<>();
System.out.println(Arrays.toString(charArray));
for(int i=0 ; i<=charArray.length-1; i++){
if(duplicateList.contains(charArray[i]))
continue;
for(int j=0 ; j<=charArray.length-1; j++){
if(i==j)
continue;
if(charArray[i] == charArray[j]){
duplicateList.add(charArray[j]);
System.out.println("Dupliate at "+i+" and "+j);
}
}
}
}
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;
}
}
}
}
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).
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]);
}