The goal of the code is to find the numbers that add up to the targetNumber. For example, if the targetNumber = 9 then the code should get the first two occuring indexes of the numbers that add up to the targetNumber. When I run my code, the output looks like the following:
The indexes are 10 and 1
What's wrong with the logic of the code? Thanks in advance!
public class TwoSum {
public static void main(String[] args){
int[] myArray = {1, 6, 43, 22, 4, 6, 4, 3, 8, 7, 3};
int targetNumber = 9;
int index1 = 0;;
int index2 = 0;
for(int i = 0; i < myArray.length; i++){
for(int j = 1; j < myArray.length; j++){
if(myArray[i] + myArray[j] == targetNumber){
index1 = i;
index2 = j;
break;
}
}
}
System.out.println("The indexes are " + index1 + " and " + index2);
}
}
When you break, you only break out of the inner loop, so instead of printing out 1 and then 10, the outer loop continues, terminating naturally, and resulting in the print out of index 10 then index 1.
An interesting result of this is that your code essentially finds the last pair of numbers that sum to targetNumber, rather than the first. If you made your for loops count down instead of up, the code should spit out the correct values, although it wouldn't be very efficient...
I believe you're expecting indexes 0 and 8 (values 1 and 8). The problem is that your break statement only breaks from the inner loop and not the outer loop. You need to use a flag to know that you also should break from the outer loop. Also consider printing a message if no match is found.
public static void main(String[] args) throws Exception {
int[] myArray = {1, 6, 43, 22, 4, 6, 4, 3, 8, 7, 3};
int targetNumber = 9;
int index1 = 0;
int index2 = 0;
boolean stop = false;
for (int i = 0; i < myArray.length && !stop; i++) {
for (int j = i + 1; j < myArray.length && !stop; j++) {
if (myArray[i] + myArray[j] == targetNumber) {
stop = true;
index1 = i;
index2 = j;
}
}
}
System.out.println(stop
? "The indexes are " + index1 + " and " + index2
: "No match found");
}
Or just print the results inside the inner loop and use a return instead of a break. This way you don't have to use a flag.
public static void main(String[] args) throws Exception {
int[] myArray = {1, 6, 43, 22, 4, 6, 4, 3, 8, 7, 3};
int targetNumber = 9;
for(int i = 0; i < myArray.length; i++){
for(int j = i + 1; j < myArray.length; j++){
if(myArray[i] + myArray[j] == targetNumber){
System.out.println("The indexes are " + i + " and " + j);
return;
}
}
}
System.out.println("No match found");
}
Results:
The indexes are 0 and 8
To make the code a little cleaner; that is, entirely foregoing the break statement, you should introduce a boolean variable called found to your loops. This way, you can break out of both of them more intuitively if you find your first match.
boolean found = false;
for(int i = 0; i < myArray.length && !found; i++){
for(int j = 1; j < myArray.length && !found; j++){
if(myArray[i] + myArray[j] == targetNumber){
found = true;
index1 = i;
index2 = j;
}
}
}
System.out.println("The indexes are " + index1 + " and " + index2);
If you're ever curious about what other pairs of numbers add up to your target, create a Pair<T> class which can store that kind of info. You wouldn't break out of any loops as you're essentially bruteforcing the entire thing.
class Pair<T> {
final T firstValue;
final T secondValue;
Pair(T firstValue, T secondValue) {
this.firstValue = firstValue;
this.secondValue = secondValue;
}
public T getFirstValue() {
return firstValue;
}
public T getSecondValue() {
return secondValue;
}
#Override
public String toString() {
return "{" + firstValue + ", " + secondValue + "}";
}
}
// later in your code
List<Pair<Integer>> pairs = new ArrayList<>();
for(int i = 0; i < myArray.length; i++){
for(int j = 1; j < myArray.length; j++){
if(myArray[i] + myArray[j] == targetNumber){
pairs.add(new Pair<>(i, j));
}
}
}
System.out.println("The indexes are " + pairs);
The above prints out:
The indexes are [{0, 8}, {1, 7}, {1, 10}, {5, 7}, {5, 10}, {7, 1}, {7, 5}, {10, 1}, {10, 5}]
The break statement is breaking the inner loop but not the outer one. So its getting the last result of 3 and 6 instead of the 1 and 8.
A more appropriate way may be:
bool found=false;
for(int i = 0; i < myArray.length; i++){
if(!found){
for(int j = 1; j < myArray.length; j++){
if(myArray[i] + myArray[j] == targetNumber){
index1 = i; index2 = j;
found=true;
break;
} } }}
There are three things that are wrong with your code:
According to specification, you want to find first matching indices, while
you actually are finding last. That happens because break breaks only inner loop. The easy fix is to use label (outer:). Although the cleaner approach would be using dedicated method to do the search and return the first matched value.
You are checking pairs of indices twice and also checking pairs of the same index. The idiomatic approach that eliminates this redundancy is to start nested loop from the current value of the index of the outer loop (j = i) or (j = i + 1) if you don't want to have pairs of the same index (i, i).
You are not considering the situation when no matching index is found. In this case you will show that (0,0) is the result.
Here is your code fixed:
public static class TwoSum {
public static void main(String[] args) {
int[] myArray = {1, 6, 43, 22, 4, 6, 4, 3, 8, 7, 3};
int targetNumber = 9;
int index1 = -1;
int index2 = -1;
outer:
for (int i = 0; i < myArray.length; i++) {
for (int j = i + 1; j < myArray.length; j++) {
if (myArray[i] + myArray[j] == targetNumber) {
index1 = i;
index2 = j;
break outer;
}
}
}
if (index1 >= 0) {
System.out.println("The indexes are " + index1 + " and " + index2 + "(Values " + myArray[index1] +
" and " + myArray[index2] + ")");
} else {
System.out.println("Not found");
}
}
}
Related
public static void printOrganizedList(int[] array) {
int[] temp = array;
System.out.println("N Count");
for(int i = 0; i < array.length; i++) {
int count = 0;
for (int j = 0; j < array.length; j++) {
if(array[i] == array[j]) {
count++;
}
}
for(int n = i-1; n > 0; n--) {
if(array[n] == array[i]) {
break;
}
else {
System.out.println(array[i] + " " + count);
}
}
}
}
This method is made to take in an array and print the duplicate values along with the amount of times it appears in the array. Like this:
-12, 3, -12, 4, 1, 1, -12, 1, 1, 2, 3, 4, 2, 3, -12
The program output should be:
N Count
4 2
3 3
2 2
1 4
-1 1
-12 4
My issue is that no matter what I try the method always spits out the duplicate number along with its amount of repeats as many times as it is repeated. So instead of outputting
"-12 4"
It will output :
"-12 4"
"-12 4"
"-12 4"
"-12 4"
Also I'm aware that there are more advanced and efficient techniques but we haven't learned a lot of that stuff yet.
Thanks in advance.
This can be easily acheived using a HashMap. You can create a Hashmap which would save the element as key and keep the number of occurrences as the value.
public static void printOrganizedList(int[] array) {
System.out.println("N Count");
HashMap<Integer, Integer> countMap = new HashMap<>();
for (int i = 0; i < array.length; i++){
if (countMap.containsKey(array[i])){
int count = countMap.get(array[i]);
countMap.replace(array[i], count + 1);
}else{
countMap.put(array[i], 1);
}
}
Iterator iterator = countMap.entrySet().iterator();
while (iterator.hasNext()){
Map.Entry mapElement = (Map.Entry) iterator.next();
int key = (int) mapElement.getKey();
int count = (int) mapElement.getValue();
System.out.println(key + " " + count);
}
}
Also the time complexity of the program that you have written goes to O(N^2) which can be a really big bottleneck when it comes to large programs.
The above program with hashmap implementation would only cost you O(N)
If the range of the input array is reasonable (for instance, from -12 to 12, not from Integer.MIN_VALUE to Long.MAX_VALUE), you may apply count sorting:
define min and max values in the array,
count the frequencies,
and print out the numbers whose frequencies are greater than 1:
int min = arr[0], max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] < min) min = arr[i];
else if (arr[i] > max) max = arr[i];
}
int[] freq = new int[max - min + 1];
for (int i = 0; i < arr.length; i++) {
freq[min + i]++;
}
for (int i = 0; i < freq.length; i++) {
if (freq[min + i] > 1) {
System.out.println((min + i) + " " + freq[min + i]);
}
}
public static void main(String[] args) {
printOrganizedList(new int[] { -12, 3, -12, 4, 1, 1, -12, 1, 1, 2, 3, 4, 2, 3, -12 });
}
public static void printOrganizedList(int[] array) {
System.out.println("N\tCount");
Map<Integer, Integer> freq = new TreeMap<>();
for (int i = 0; i < array.length; i++) {
if (freq.containsKey(Integer.valueOf(array[i])))
freq.put(Integer.valueOf(array[i]), freq.get(Integer.valueOf(array[i])) + 1);
else
freq.put(Integer.valueOf(array[i]), 1);
}
for (Integer key : freq.keySet()) {
System.out.println(key + "\t" + freq.get(key));
}
}
, output
N Count
-12 4
1 4
2 2
3 3
4 2
, Another solution to match your code
public static void printOrganizedList(int[] array) {
System.out.println("N\tCount");
Arrays.sort(array);
for (int i = 0; i < array.length; i++) {
int count = 0;
// calc freq
for (int j = 0; j < array.length; j++) {
if (array[i] == array[j])
count++;
}
if (count > 1)
System.out.println(array[i] + "\t" + count);
i += count;
}
}
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);
}
This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 3 years ago.
I have two sorted arrays. I need to connect both of them into one new sorted array:
int[] arr1 = {1,2,3,6,8};
int[] arr2 = {4,5,9,12,208,234};
printArr(allSort(arr2,arr1));
}
public static int[] allSort(int[] arr, int[] arr3) {
int[] newArr = new int[arr.length + arr3.length];
int j = 0;
int k = 0;
for (int i = 0; i < newArr.length - 1; i++) {
if(j == arr3.length){
newArr[i] = arr[k];
k++;
}
if(k == arr.length){
newArr[i] = arr3[j];
j++;
}
if(arr[k] > arr3[j]){
newArr[i] = arr3[j];
j++;
} else if (arr[k] < arr3[j]) {
newArr[i] = arr[k];
k++;
}
}
return newArr;
}
I tried to build an array that has a length equal to the length of the both arrays summed together and then run a loop on it.
However, this code returns the error: AArrayIndexOutOfBoundsException: 5.
Just add continue in both the if condition like this,
if(j == arr3.length){
newArr[i] = arr[k];
k++;
continue;
}
if(k == arr.length){
newArr[i] = arr3[j];
j++;
continue;
}
So here anyway the other loop is completed thats why we are iterating and adding all the values so it doesn't need to check all other conditions so we can skip it.
Also,
for (int i = 0; **i < newArr.length**; i++)
Since you are checking "<".
The ArrayIndexOutOfBoundsException() is an Exception and what it basically means is that at some point you're trying to access a element of an array with an illegal index. Refer to the ArrayIndexOutOfBoundsException Documentation for more informations.
after looking to your code at some point here are the index's values:
.
In the loop you're calling arr[k] with k = 5 in if(arr[k] > arr3[j]) as arr is an Array of length 5 and thus has a maximum index of 4 and that is why you're getting an out of bounds exception.
Your main problem is control when first array finished.
I made some adjusts on your code and now it's working.
public static void main(String[] args) {
int[] arr1 = { 1, 2, 3, 6, 8 };
int[] arr2 = { 4, 5, 9, 12, 208, 234 };
int[] newArr = allSort(arr1, arr2);
for (int i = 0; i <= newArr.length - 1; i++) {
System.out.println(" " + newArr[i]);
}
}
public static int[] allSort(int[] arr1, int[] arr2) {
int j = 0;
int k = 0;
boolean endArr1 = false;
int[] newArr = new int[arr1.length + arr2.length];
for (int i = 0; i <= newArr.length - 1; i++) {
if (arr1[k] < arr2[j] && !endArr1) {
System.out.println("k: " + k + " " + arr1.length);
newArr[i] = arr1[k];
if(k < arr1.length-1)
k++;
else
endArr1 = true;
} else if (arr2[j] < arr1[k] || endArr1) {
System.out.println("j: " + j + " " + arr2.length);
newArr[i] = arr2[j];
if(j < arr2.length-1)
j++;
}
}
return newArr;
}
I need to finish this code which involves deleting all the zero's stored in the array. I thought it was complete but it won't compile, it's my last line that is dubios and I'm not getting right. Thank you.
public class DeleteZero {
public static int[] array(int[] a) {
int k = 0;
for (int i = 0; i < a.length; i++) {
if (a[i] !=0)
k++;
}
int[] b = new int[k];
int t = 0;
for (int i = 0; i < a.length; i++) {
if (a[i] != 0) {
b[t] = a[i];
t++;
}
}
return b;
}
public static void main (String args[]) {
int[] rand = new int[20];
for (int i = 0; i < 20; i++) {
rand[i] = (int)(Math.random());
}
System.out.println(array(a));
}
}
Few errors.
This would always insert 0 at rand[i] because you are casting Math.random() to int which will always become zero.
rand[i] = (int)(Math.random());
Change it to sth like this. I have written 10 but you can write any number to define the range.
rand[i] = (int)(Math.random()*10);
This line is also wrong:
System.out.println(array(a));
You need to print the array by looping over it, but more importantly your function array() returns a new array, which should be stored somewhere before printing it.
Here is a possible workaround
rand = array(rand);
for (int i=0; i<rand.length; i++){
System.out.println(rand[i]);
}
The compile time error is due to the fact that, in the main method you have created the array named rand and passing the array named a. from the main method call System.out.print(array(rand))
You can try Java 8's Stream, which turns the whole logic to one line return Arrays.stream(a).filter(n -> n!= 0).toArray();
Little fixed your code:
import java.util.Random; // Import Random
public class DeleteZero {
public static int[] array(int[] a) {
int k = 0;
for (int i = 0; i < a.length; i++) {
if (a[i] !=0)
k++;
}
int[] b = new int[k];
int t = 0;
for (int i = 0; i < a.length; i++) {
if (a[i] != 0) {
b[t] = a[i];
t++;
} else {
System.out.println("Skip at position: [" + i + "] because a[i] == "+a[i]+";"); // Display what removed.
}
}
return b;
}
public static void main (String args[]) {
int[] rand = new int[20];
Random rnd = new Random();
for (int i = 0; i < 20; i++) {
rand[i] = rnd.nextInt(11) + 0; // 11-1 = max, 0 = min
}
int[] a = array(rand);
System.out.println(a); // since it prints something like this: [I#106d69c, we should print all elements manually through a loop.
System.out.println("a.length = " + a.length + ", rand length: " + rand.length);
System.out.print("[");
for (int i = 0; i != a.length; i++) {
String space = ", ";
if (i == a.length-1) //if last not print space
space = "";
System.out.print(a[i]+space); // Print all elements
}
System.out.print("]\n");
}
}
Example of output:
Skip at position: [2] because a[i] == 0;
Skip at position: [8] because a[i] == 0;
Skip at position: [10] because a[i] == 0;
Skip at position: [12] because a[i] == 0;
Skip at position: [16] because a[i] == 0;
[I#106d69c
a.length = 15, rand length: 20
[6, 8, 1, 8, 7, 1, 3, 5, 3, 8, 5, 2, 7, 2, 8]
I am trying to make my existing implementation of Prim's algorithm to keep track distances from source . Since prim's and Dijkstra's algorithm are almost same. I can't figure out where am I missing something.
I know what the problem is but cannot figure it out.
Here is my code, how do I modify it to print the shortest distance from source to all other vertex. Shortest distance is stored in array named : dist[]
Code:
package Graphs;
import java.util.ArrayList;
public class Prims {
static int no_of_vertices = 0;
public static void main(String[] args) {
int[][] graph = {{0, 2, 0, 6, 0},
{2, 0, 3, 8, 5},
{0, 3, 0, 0, 7},
{6, 8, 0, 0, 9},
{0, 5, 7, 9, 0},
};
no_of_vertices = graph.length;
int [][] result = new int [no_of_vertices][no_of_vertices];
boolean[] visited = new boolean[no_of_vertices];
int dist[] = new int[no_of_vertices];
for (int i = 0; i < no_of_vertices; i++)
for (int j = 0; j < no_of_vertices; j++) {
result[i][j]= 0;
if (graph[i][j] == 0) {
graph[i][j] = Integer.MAX_VALUE;
}
}
for (int i = 0; i < no_of_vertices; i++) {
visited[i] = false;
dist[i] = 0;
}
ArrayList<String> arr = new ArrayList<String>();
int min;
visited[0] = true;
int counter = 0;
while (counter < no_of_vertices - 1) {
min = 999;
for (int i = 0; i < no_of_vertices; i++) {
if (visited[i] == true) {
for (int j = 0; j < no_of_vertices; j++) {
if (!visited[j] && min > graph[i][j]) {
min = graph[i][j];
dist[i] += min; // <------ Problem here
visited[j] = true;
arr.add("Src :" + i + " Destination : " + j
+ " Weight : " + min);
}
}
}
}
counter++;
}
for (int i = 0; i < no_of_vertices; i++) {
System.out.println("Source : 0" + " Destination : " + i
+ " distance : " + dist[i]);
}
for (String str : arr) {
System.out.println(str);
}
}
}
There is a mistake in calculation of distance array as it forgets to add the distance of any intermediate nodes from source to destination.
for (int j = 0; j < no_of_vertices; j++) {
if (!visited[j] && min > graph[i][j]) {
min = graph[i][j];
dist[i] += min; // <------ Problem here
Of course intermediate edges don't get added, because you only add the current edge. You probably want something like:
if (dist[i] + graph[i][j] < dist[j])
dist[j] = dist[i] + graph[i][j];
And get rid of the min variable.
Although your algorithm does not look correct to me. You're supposed to pick the node with minimum d[] at each step, and update that node's neighbors as I wrote above, then mark it as picked and never pick it again.