Search minimum absolute value difference in java - java

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)

Related

Remove an Element in Array on Leet code. I am getting an error of getting incompatible types and I dont know whats wrong

Here is the question:
Given an integer array nums and an integer val, remove all
occurrences of val in nums in place. The relative order of the
elements may be changed.
Since it is impossible to change the length of the array in some
languages, you must instead have the result be placed in the first
part of the array nums.
More formally, if there are k elements after removing the duplicates,
then the first k elements of nums should hold the final result. It
does not matter what you leave beyond the first k elements.
Return k after placing the final result in the first k slots of
nums.
Do not allocate extra space for another array. You must do this by
modifying the input array in-place with O(1) extra memory.
I've tried to remove the given target val by shifting the value to the end of the array index by iteration of nums.length-1 every time the val is found in the given array. I just want to know what's wrong with my approach.
Below is the code I've tried:
class Solution {
public int removeElement(int[] nums, int val) {
for (int i = 0; i < nums.length; i++) {
if (val == nums[i]) {
for (int j = i; j < nums.length - 1; j++) {
nums[j + 1] = nums[j];
}
break;
}
}
return nums;
}
}
Your algorithm correctly would be the following. The error was returning the array, but that was changed in-situ. You should have returned the new reduced length.
public int removeElement(int[] nums, int val) {
int k = nums.length;
for (int i = 0; i < k; i++) {
if (val == nums[i]) {
--k;
//for (int j = i; i < k; j++) {
// nums[j] = nums[j + 1];
//}
System.arraycopy(nums, i+1, nums, i, k-i);
--i; // Check the new nums[i] too
}
}
return k;
}
The for-j loop can be replaced with System.arraycopy (which handles overlapping of the same array too).
Or:
public int removeElement(int[] nums, int val) {
int k = 0;
for (int i = 0; i < n; i++) {
if (val != nums[i]) {
nums[k] = nums[i];
++k;
}
}
return k;
}
This is my code in leetcode. Hope will help you
class Solution {
public int removeElement(int[] nums, int val) {
ArrayList<Integer> list = new ArrayList<>();
for(int i=0;i<nums.length;i++){
if(nums[i]!=val){
list.add(nums[i]);
}
}
for(int i=0;i<list.size();i++){
nums[i]= list.get(i);
}
return list.size();
}
}

How to return an array with the indexes of a certain int from another array

I'm a beginner Java student and I have been trying to write a method that lists all indexes of a certain int within an array. What I've done so far is store the value of that int at its corresponding index within another array but the best I can do is set the values of all other indexes that are not equal to the original int to -1.
I think I need to store the value i within the array and delete all the -1s but I don't know how to do this. By the way, these values are -1 because all my arrays in this program contain ints that are between 0-100. What would I do if possible ints within this array could be any number?
Also surely there is an easier or more efficient way of doing this.
public static int[] maxValueIndex(int[] arr, int targetValue, int x) {
int[] maxValue = new int[x];
for (int i = 0; i < arr.length; i++) {
if (arr[i] == targetValue) {
maxValue[i] = arr[i];
} else {
maxValue[i] = -1;
}
}
return maxValue;
}
If I understood your query correctly then you want an array with all the indices i such that arr[i]==targetValue. We can achieve this efficiently using any dynamic data structure. Like, use an ArrayList and keep adding all the desired indices one by one then convert the List to an array and return it.
Something like this:
List<Integer> index = new ArrayList<Integer>();
for (int i = 0; i < arr.length; i++)
{
if (arr[i] == targetValue)
index.add( i );
}
int[] maxValue = index.stream().mapToInt(Integer::intValue).toArray();
return maxValue;
If it is required to use arrays only to resolve this task, it may take two passes to create a compacted array containing only valid indexes:
Find the number of matches, and then create and fill a compact array
public static int[] getTargetIndexes(int targetValue, int ... arr) {
int n = arr.length;
int targetCount = 0;
for (int i = 0; i < n; i++) {
if (arr[i] == targetValue) {
targetCount++;
}
}
int[] indexes = new int[targetCount];
for (int i = 0, j = 0; j <targetCount && i < n; i++) {
if (arr[i] == targetValue) {
indexes[j++] = i;
}
}
return indexes;
}
Create an array of the same length, fill it and then compact by using Arrays.copyOf:
public static int[] getTargetIndexes(int targetValue, int ... arr) {
int n = arr.length;
int[] indexes = new int[n];
int targetCount = 0;
for (int i = 0; i < n; i++) {
if (arr[i] == targetValue) {
indexes[i] = i;
targetCount++;
} else {
indexes[i] = -1;
}
}
for (int i = 0, j = 0; j < targetCount && i < n; i++) {
if (indexes[i] > -1) {
indexes[j++] = i;
}
}
return Arrays.copyOf(indexes, targetCount); // truncate bad indexes
}
Also, the signature of the method uses vararg to pass the input array as a sequence of int -- the vararg argument int ... arr should be the last one then.
If Stream API can be used, the task may be resolved conveniently in a declarative way:
public static int[] getTargetIndexes(int targetValue, int ... arr) {
return IntStream.range(0, arr.length) // get stream of indexes
.filter(i -> arr[i] == targetValue) // keep only matching indexes
.toArray(); // build output array
}

After counting sort the result array has one more element (0) than the original one

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.

Recursion - Adding the subset of an array

I'm trying to decide if the sum of subset is a set num or not)...
I've read through most of the questions so far here on stackoverflow and have come up with nothing. I think the issue I'm finding is that I want to add together the elements in the combitorial subsets created. All together this should be done recursively. With the current code I have, I'm getting a stackoverflow error for recursion. (ironic)
So to clarify:
int[] array = {1,2,3,4,5};
the subset would be the size of say 2 and combinations would be
{1,2},{1,3},{1,4},{1,5},{2,3},{2,4},{2,5},{3,4},{3,5},{4,5}
from this data I want to see if the subset say... equals 6, then the answers would be: {1,5} and {2,4} leaving me with true as a answer. In respect to the signature I would like to keep it the same because it corresponds with another method (outside of the issue because it only sends the array, n, and num to the method)
public static boolean subset(int[] array, int n, int num) {
int count = 0;
int sum = 0;
int[] subarray = new int[n];
int[] temp = new int[array.length - 1];
int[] copy = array;
subarray[count] = array[0];
for (int i = 0; i < n; i++) {
subarray[count] = array[i];
count++;
System.arraycopy(array, i, temp, 0, n);
}
for (int j = 0; j < subarray.length; j++) {
sum += subarray[j];
if (sum == num)
return true;
}
subset(copy, n, goal);
return false;
}
Not an answer but a plausible idea for one?
for (int i = 0; i < array.length; i++) {
// New sublist to store values from 0 to i
int[] list = new int[array.length - 1];
for (int j = 0; j < array.length; j++) {
list[j] = array[j+1];
}
// Here you call this recursively with your Parent list from i+1
// index and working list from 0 to i
subsetSum(list, n, goal);
}
int sum = 0;
for (int i = 0; i < array.length; i++) {
sum += array[i];
}
if (sum == goal) {
return true;
}
return false;

Finding modes an an array

Does anyone know how to find the modes in an array when there are more then one mode? I have this code that finds one mode. But I'm dealing with an array which has more than one mode, a multimodal array and I have to print each mode exactly once. Here is my code, can someone help me out? Thanks.
public static int mode(int a[])
{
int maxValue=0, maxCount=0;
for (int i = 0; i < a.length; ++i)
{
int count = 0;
for (int j = 0; j < a.length; ++j)
{
if (a[j] == a[i]) ++count;
}
if (count > maxCount)
{
maxCount = count;
maxValue = a[i];
}
}
return maxCount;
}
public static Integer[] modes(int a[])
{
List<Integer> modes = new ArrayList<Integer>();
int maxCount=0;
for (int i = 0; i < a.length; ++i)
{
int count = 0;
for(int j = 0; j < a.length; ++j)
{
if (a[j] == a[i]) ++count;
}
if (count > maxCount)
{
maxCount = count;
modes.clear();
modes.add(a[i]);
}
else if (count == maxCount)
{
modes.add(a[i]);
}
}
return modes.toArray(new Integer[modes.size()]);
}
Since your elements will be between 10 and 1000, you can use a Counter array. In this Counter array, you can store the counts of the value of the a[i] element. I think you can understand this better in code:
public static List<Integer> mode(int[] a) {
List<Integer> lstMode = new ArrayList<Integer>();
final int MAX_RANGE = 1001;
int[] counterArray = new int[MAX_RANGE]; //can be improved with some maths :)!
//setting the counts for the counter array.
for (int x : a) {
counterArray[x]++;
}
//finding the max value (mode).
int maxCount = counterArray[0];
for(int i = 0; i < MAX_RANGE; i++) {
if (maxCount < counterArray[i]) {
maxCount = counterArray[i];
}
}
//getting all the max values
for(int i = 0; i < MAX_RANGE; i++) {
if (maxCount == counterArray[i]) {
lstMode.add(new Integer(i));
}
}
return lstMode;
}
If your input will have elements outside of 1000, you can look for the Map answer (like in other posts).
We should do this the easy way and utilize a Map data structure in the following format:
Map<Integer,Integer>
And then keep a running total, afterwards you iterate over the keyset and pull the highest value(s) from the Map.
If you want to stay with the List implementation you can do the following to remove dupes:
Set s = new HashSet(list);
list = new ArrayList(s);
One approach is to run (approximately) your current code twice: the first time, find maxCount, and the second time, print out each value that occurs maxCount times. (You'll need to make some modifications in order to print each mode only once, instead of printing it maxCount times.)
Instead of having a single maxValue, store the modes in an ArrayList<Integer>.
if (count == maxCount)
{
modes.add(a[i]);
}
else if (count > maxCount)
{
modes.clear(); // discard all the old modes
modes.add(a[i]);
maxCount = count;
}
and start with j = i instead of j = 0.
Since your array values only range from [10,1000], you could use a Map<Integer,Integer> to store a mapping between each discovered array value (map key) and its count (map value). A HashMap would work very well here.
To increment the count:
int count = (map.contains(a[i]) ? map.get(a[i]) : 1;
map.put(a[i],count);
Continue to track the max count like you already do, and at the end, just iterate over the map and collect all map keys with a map value equal to the max count.

Categories

Resources