How to get indexOf element which isn't the first [duplicate] - java

This question already has answers here:
Trying to find all occurrences of an object in Arraylist, in java
(6 answers)
Closed 3 years ago.
Assumed
ArrayList<Integer> list = Arrays.asList(new Integer[] {1,2,3,4,5,6,1,8,9});
Find second occurence
I want to get the index of the second finding of the (multiple) contained element "1" but list.indexOf(1) will always return 0 (as it's the first finding).
Performance
I want to do this without using loops like for or while.
Since I need it for a game, using loops wouldn't be efficient at all.
EDIT: Is there any way to get "indexOf" some element without iterator ?

You cannot do this without iterating.
indexOf iterates, for example.
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
Same is valid for lastIndexOf.
As you can see no Iterator<Integer> is used at all, if that is what worries you.
And, btw, this isn't a performance concern.
Do you have arrays with millions of elements? If you have, consider changing data structure type.

If you are very much concerned about performance, use a HashMap<Integer, List<Integer>>. Then if your want n'th occurence of an element m, you can do map.get(m).get(n). Your map contains elements and their corresponding indexes.
Once your map is built, the time complexity for your query would be O(1)
Example:
public static void main(String[] args){
int[] a = {1, 2, 1, 3, 4, 1};
Map<Integer, List<Integer>> map = new HashMap<Integer, List<Integer>>();
for(int i = 0; i < a.length; i++){
if(map.containsKey(a[i])){
map.get(a[i]).add(i);
}else{
map.put(a[i], new ArrayList<Integer>());
map.get(a[i]).add(i);
}
}
// second index of 1. Note that index starts from 0.
System.out.println(map.get(1).get(1));
}
Result:
2

list.subList(list.indexOf(1) + 1, list.size()).indexOf(1)

list.indexOf(1, list.indexOf(1) + 1);
The first parameter 1 being the object to be searched.
The second parameter list.indexOf(1) + 1 being the starting index for the search.

Related

How to remove the first first occurrence of the specified element in an int array? (java) [duplicate]

This question already has answers here:
How do I remove objects from an array in Java?
(20 answers)
Closed 4 years ago.
I have this method header:
public boolean remove(Object anObject)
{....}
I need the body of the method to remove the first occurrence of a specified element from an int array and shift the remaining elements in the array to the left. I have thought about starting with
for (int i = 0; i < arr.length; i++) {
if (arr[i] == anObject)
}
but this is not working as expected.
Any help would be great, thanks!
I have a solution for you. Use a for loop that runs and shifts all of your array data over by one.
Building off of your original code:
for (int i = 0; i < arr.length-1; i++) {
if (arr[i].equals(anObject)){
for (int k = i; k < arr.length; k++){ //starts replacing ON the duplicate value
arr[k] = arr[k+1]; //replaces the value with the 1 higher one; aka moving all your array values left
}
}
And like what #camickr said:
You need to use stringName.equals(Object); to compare strings because they are non-primative data types.
Hope this helps. Good luck.
What you're trying to achieve can be done quite easily through the use of an ArrayList, as camickr mentioned. Overall, the use off ArrayLists for objects can be considered better practice in general.
Simply declare an ArrayList of type the object you are using, and add and remove instances of said object by using
myArrayList.add(object);
myArrayList.remove(index);
Here's a solution that works using only true array of objects, rather than any of the Java Collections. The outline of how this works in pseudocode is:
Iterate through all members of the array, checking for equality to anObject.
When a match is found, remove the element.
Iterate through the remaining members of the array, shifting them forward one spot.
At the end of the array, mark the final member as null.
I've included some extra code that won't be necessary for your assignment, but will help you to visualize how the method is working on the array:
public class ArrayMethodTester {
private Object[] array = {3, 5, 1, 6, 8, 7, 0, 9, 2, 4};
public static void main(String[] args) {
ArrayMethodTester testArray = new ArrayMethodTester();
testArray.printArray();
testArray.remove(7);
testArray.printArray();
}
public boolean remove(Object anObject) {
for (int i = 0; i < array.length; i++) {
if(array[i].equals(anObject)) {
for (int j = i; j < array.length - 1; j++) {
array[j] = array[j + 1];
}
array[array.length - 1] = null;
return true;
}
}
return false;
}
private void printArray() {
System.out.printf("[%s", array[0]);
for (int i = 1; i < array.length; i++) {
System.out.printf(",%s", array[i]);
}
System.out.println("]");
}
}
but i learned this will not get me my answer
if (arr[i] == anObject)
You should NOT be using "==" for object comparison.
if (arr[i].equals(anObject))
Instead you should be using the equals(..) method.
Then once you know the index of the item you want to remove. So now you just need to copy the next item to that index and repeat until you reach the end of the array. The last item would then be set to null to indicate no value exists.

Java program to find the duplicate values of an array of integer using simple loop

public class ArrayTest{
public static void main(String[] args) {
int array[] = {32,3,3,4,5,6,88,98,9,9,9,9,9,9,1,2,3,4,5,6,4,3,7,7,8,8,88,88};
for(int i= 0;i<array.length-1;i++){
for(int j=i+1;j<array.length;j++){
if((array[i])==(array[j]) && (i != j)){
System.out.println("element occuring twice are:" + array[j]);
}
}
}
}
}
this program work fine but when i compile it, it print the values again and again i want to print the duplicate value once for example if 9 is present 5 times in array so it print 9 once and if 5 is present 6 times or more it simply print 5...and so on....this what i want to be done. but this program not behave like that so what am i missing here.
your help would be highly appreciated.
regards!
Sort the array so you can get all the like values together.
public class ArrayTest{
public static void main(String[] args) {
int array[] = {32,3,3,4,5,6,88,98,9,9,9,9,9,9,1,2,3,4,5,6,4,3,7,7,8,8,88,88};
Arrays.sort(array);
for (int a = 0; a < array.length-1; a++) {
boolean duplicate = false;
while (array[a+1] == array[a]) {
a++;
duplicate = true;
}
if (duplicate) System.out.println("Duplicate is " + array[a]);
}
}
}
The problem statement is not clear, but lets assume you can't sort (otherwise the problem greatly simplifies). Lets also assume the space complexity is constrained, and you can't keep a Map, etc, for counting the frequency.
You can use use lookbehind, but this unnecessarily increases the time complexity.
I think a reasonable approach is to reserve the value -1 to indicate that an array position has been processed. As you process the array, you update each active value with -1. For example, if the first element is 32, then you scan the array for any value 32, and replace with -1. The time complexity does not exceed O(n^2).
This leaves the awkcase case where -1 is an actual value. It would be required to do a O(n) scan for -1 prior to the main code.
If the array must be preserved, then clone it prior to processing. The O(n^2) loop is:
for (int i = 0; i < array.length - 1; i++) {
boolean multiple = false;
for (int j = i + 1; j < array.length && array[i] != -1; j++) {
if (array[i] == array[j]) {
multiple = true;
array[j] = -1;
}
}
if (multiple)
System.out.println("element occuring multiple times is:" + array[i]);
}
What you can do, is use a data structure that only contains unique values, Set. In this case we use a HashSet to store all the duplicates. Then you check if the Set contains your value at index i, if it does not then we loop through the array to try and find a duplicate. If the Set contains that number already, we know it's been found before and we skip the second for loop.
int array[] = {32,3,3,4,5,6,88,98,9,9,9,9,9,9,1,2,3,4,5,6,4,3,7,7,8,8,88,88};
HashSet<Integer> duplicates = new HashSet<>();
for(int i= 0;i<array.length-1;i++)
{
if(!duplicates.contains(array[i]))
for(int j=i+1;j<array.length;j++)
{
if((array[i])==(array[j]) && (i != j)){
duplicates.add(array[i]);
break;
}
}
}
System.out.println(duplicates.toString());
Outputs
[3, 4, 5, 6, 7, 88, 8, 9]
I recommend using a Map to determine whether a value has been duplicated.
Values that have occurred more than once would be considered as duplicates.
P.S. For duplicates, using a set abstract data type would be ideal (HashSet would be the implementation of the ADT), since lookup times are O(1) since it uses a hashing algorithm to map values to array indexes. I am using a map here, since we already have a solution using a set. In essence, apart from the data structure used, the logic is almost identical.
For more information on the map data structure, click here.
Instead of writing nested loops, you can just write two for loops, resulting in a solution with linear time complexity.
public void printDuplicates(int[] array) {
Map<Integer, Integer> numberMap = new HashMap<>();
// Loop through array and mark occurring items
for (int i : array) {
// If key exists, it is a duplicate
if (numberMap.containsKey(i)) {
numberMap.put(i, numberMap.get(i) + 1);
} else {
numberMap.put(i, 1);
}
}
for (Integer key : numberMap.keySet()) {
// anything with more than one occurrence is a duplicate
if (numberMap.get(key) > 1) {
System.out.println(key + " is a reoccurring number that occurs " + numberMap.get(key) + " times");
}
}
}
Assuming that the code is added to ArrayTest class, you could all it like this.
public class ArrayTest {
public static void main(String[] args) {
int array[] = {32,3,3,4,5,6,88,98,9,9,9,9,9,9,1,2,3,4,5,6,4,3,7,7,8,8,88,88};
ArrayTest test = new ArrayTest();
test.printDuplicates(array);
}
}
If you want to change the code above to look for numbers that reoccur exactly twice (not more than once), you can change the following code
if (numberMap.get(key) > 1) to if (numberMap.get(key) == 2)
Note: this solution takes O(n) memory, so if memory is an issue, Ian's solution above would be the right approach (using a nested loop).
// print duplicates
StringBuilder sb = new StringBuilder();
int[] arr = {1, 2, 3, 4, 5, 6, 7, 2, 3, 4};
int l = arr.length;
for (int i = 0; i < l; i++)
{
for (int j = i + 1; j < l; j++)
{
if (arr[i] == arr[j])
{
sb.append(arr[i] + " ");
}
}
}
System.out.println(sb);
Sort the array. Look at the one ahead to see if it is duplicate. Also look at one behind to see if this was already counted as duplicate (except when i == 0, do not look back).
import java.util.Arrays;
public class ArrayTest{
public static void main(String[] args) {
int array[] = {32,32,3,3,4,5,6,88,98,9,9,9,9,9,9,1,2,3,4,5,6,4,3,7,7,8,8,88,88};
Arrays.sort(array);
for(int i= 0;i<array.length-1;i++){
if((array[i])==(array[i+1]) && (i == 0 || (array[i]) != (array[i-1]))){
System.out.println("element occuring twice are:" + array[i]);
}
}
}
}
prints:
element occuring twice are:3
element occuring twice are:4
element occuring twice are:5
element occuring twice are:6
element occuring twice are:7
element occuring twice are:8
element occuring twice are:9
element occuring twice are:32
element occuring twice are:88

Can't find solution to codingbat array challenge

I have been working on codingbat problems for java and have come across a problem in array-2 which I cannot solve using only one loop. The problem is as follows :
Given a non-empty array of ints, return a new array containing the elements from the original array that come before the first 4 in the original array. The original array will contain at least one 4. Note that it is valid in java to create an array of length 0.
I looked at other solutions but they all use two loops, and the Array-2 problem set should be done using only one loop. I am not sure how to approach this, here is my solution with two loops :
public int[] pre4(int[] nums) {
int[] notnums = new int[0];
for(int i = 0; i<nums.length;i++)
if(nums[i]==4){
notnums = new int[i];
for(int j = 0;j<i;j++)
notnums[j] = nums[j];
return notnums;
}
return notnums;
}
As it's a coding challenge, I won't answer with code, instead, here's how you should approach it:
Declare another array
Start iterating first array, element by element
If the element is 4, break out of loop
If the element is not 4, add it into another array
In the end, second array should have all the elements that are present before first 4.
my solution for 1 loop:
public int[] pre4(int[] nums) {
int[] res = new int[0];
for(int i = nums.length - 1; i >= 0; i--){
if (nums[i] == 4)
res = new int[i];
else
if (res.length > 0)
res[i] = nums[i];
}
return res;
}

Two sum - Doesn't work

Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Consider input [3,2,4] and target is 6. I added (3,0) and (2,1) to the map and when I come to 4 and calculate value as 6 - 4 as 2 and when I check if 2 is a key present in map or not, it does not go in if loop.
I should get output as [1,2] which are the indices for 2 and 4 respectively
public int[] twoSum(int[] nums, int target) {
int len = nums.length;
int[] arr = new int[2];
Map<Integer,Integer> map = new HashMap<Integer,Integer>();
for(int i = 0;i < len; i++)
{
int value = nums[i] - target;
if(map.containsKey(value))
{
System.out.println("Hello");
arr[0] = value;
arr[1] = map.get(value);
return arr;
}
else
{
map.put(nums[i],i);
}
}
return null;
}
I don't get where the problem is, please help me out
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice. Consider input [3,2,4] and target is 6. I added (3,0) and (2,1) to the map and when I come to 4 and calculate value as 6 - 4 as 2 and when I check if 2 is a key present in map or not, it does not go in if loop.
Okay, let's take a step back for a second.
You have a list of values, [3,2,4]. You need to know which two will add up 6, well, by looking at it we know that the answer should be [1,2] (values 2 and 4)
The question now is, how do you do that programmatically
The solution is (to be honest), very simple, you need two loops, this allows you to compare each element in the list with every other element in the list
for (int outter = 0; outter < values.length; outter++) {
int outterValue = values[outter];
for (int inner = 0; inner < values.length; inner++) {
if (inner != outter) { // Don't want to compare the same index
int innerValue = values[inner];
if (innerValue + outterValue == targetValue) {
// The outter and inner indices now form the answer
}
}
}
}
While not highly efficient (yes, it would be easy to optimise the inner loop, but given the OP's current attempt, I forewent it), this is VERY simple example of how you might achieve what is actually a very common problem
int value = nums[i] - target;
Your subtraction is backwards, as nums[i] is probably smaller than target. So value is getting set to a negative number. The following would be better:
int value = target - nums[i];
(Fixing this won't fix your whole program, but it explains why you're getting the behavior that you are.)
This code for twoSum might help you. For the inputs of integer array, it will return the indices of the array if the sum of the values = target.
public static int[] twoSum(int[] nums, int target) {
int[] indices = new int[2];
outerloop:
for(int i = 0; i < nums.length; i++){
for(int j = 0; j < nums.length; j++){
if((nums[i]+nums[j]) == target){
indices[0] = i;
indices[1] = j;
break outerloop;
}
}
}
return indices;
}
You can call the function using
int[] num = {1,2,3};
int[] out = twoSum(num,4);
System.out.println(out[0]);
System.out.println(out[1]);
Output:
0
2
You should update the way you compute for the value as follows:
int value = target - nums[i];
You can also check this video if you want to better visualize it. It includes Brute force and Linear approach:

Why do I get an ArrayIndexOutOfBoundsException For My ArrayList [duplicate]

This question already has answers here:
What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?
(5 answers)
Closed 8 years ago.
I cannot see anything wrong with my code:-
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
int[] A = new int[] {2, 1, 1, 2, 3, 1};
ArrayList<Integer> foundNumbers = new ArrayList<>();
int distinct = 0;
for(int i = 0; i < A.length-1; i++) {
if(foundNumbers.get(i-1) == null) {
foundNumbers.set((i-1), A[i]);
distinct++;
}
}
System.out.println(distinct);
}
}
I want to check if the value of Array element i has already been assigned to ArrayList element i-1, then increment the distinct variable and print how many distinct values are in the array.
Here's the exception when I change the value of i to 1:-
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:604)
at java.util.ArrayList.get(ArrayList.java:382)
at tdd.Main.main(Main.java:19)
The list is completely empty. You haven't put anything in it, yet you're trying to read elements from it with the foundNumbers.get call, so any index will be out of bounds.
To add unique elements from A to the list, get and set are simply the wrong list methods to call, use contains and add if that's what you want to do:
for (int x : A) {
if (!foundNumbers.contains(x))
foundNumbers.add(x);
}
Here is the same logic as above written in a more verbose fashion that might make it easier to understand what is involved:
for (int i = 0; i < A.length; i++) {
boolean found = false;
for (int j = 0; j < foundNumbers.size(); j++) {
if (A[i] == foundNumbers.get(j)) {
found = true;
break;
}
}
if (!found) {
foundNumbers.add(A[i]);
}
}
You don't need the separate distinct variable, since it is simply foundNumbers.size().
Although this works, a List is not very efficient for eliminating duplicates if the count of elements is large, since every contains call requires another loop through the contents of the list. A Set automatically prevent duplicates and internally structures its contents in a way that makes it efficient to do so:
Set<Integer> distinct = new TreeSet<>();
for (int x : A) distinct.add(x);
System.out.println(distinct); // [1, 2, 3]
for(int i = 0; i < A.length-1; i++) {
if(foundNumbers.get(i-1) == null) {
In the first iteration of that loop, i will be set to zero, so the second line is doing .get(-1).
There are multiple issues:
when i is 0, you try to get i-1=-1th element which is not valid
Even when you fix this, since you dont have elements in list, you will still get IndexOutOfBoundsException, since you havent stored any elements yet and your list is empty.
Your loop should be:
for (int i = 0; i < A.length - 1; i++) {
if (foundNumbers.size() > i && foundNumbers.get(i) == null) {//or better you use contains method of list like foundNumbers.contains(someNumber);
foundNumbers.add(A[i]);
distinct++;
}
}

Categories

Resources