This method due to restrictions can not use ArrayLists. The method accepts an array, the desired value to find, and then the certain number of near values. It uses integers and integer arrays only. This is what I have so far
/**
* Return the k elements of a nearest to val.
* The array a is not changed as a result of calling this method.
* This method throws an IllegalArgumentException if k is negative.
* This method returns an array of zero length if k == 0 or if
* k > a.length.
*
* #param a the array to be searched
* #param val the reference value
* #param k the number of near elements to identify
* #return the k elements a[i] such that ABS(a[i] - val)
* are the k smallest evaluations
*
*/
public static int[] nearestK(int[] a, int val, int k) {
int x = 0;
int[] answer = new int[k];
if (k < x || a.length == 0 || a == null)
{
throw new IllegalArgumentException();
}
if (k == 0 || k > a.length)
{
int[] badAnswer = new int[0];
return badAnswer;
}
int[] copy = Arrays.copyOf(a, a.length);
Arrays.sort(copy);
int nearest = copy[0];
for (int i = 0; (i < copy.length); i++) {
if (Math.abs(nearest - val) > Math.abs(copy[i] - val)) {
nearest = copy[i]; x = i;
}
}
int index = 0;
while (index < answer.length) {
answer[index] = nearest;
nearest = copy[x + (index + 1)];
index++;
}
return answer;
}
This method works sometimes but i began to realize that it only used values after the desired element.
i.e
int[1,3,5,7,10,11,12} this method, if searched for 6, with 3 nearest values, would only return
7,10,11 as an array. This clearly is not correct. I am very new to java so at this point I am wondering what are some alternatives to this or ways of correcting this method.
Here's a clever answer: Instead of sorting the array in natural order, sort it according to the distance to val. Then, all you need to do is pick the first k elements:
public static int[] nearestK(int[] a, int val, int k) {
// omitted your checks for brevity
final int value = val; // needs to be final for the comparator, you can also make the parameter final and skip this line
Integer[] copy = new Integer[a.length]; // copy the array using autoboxing
for (int i = 0; i < a.length; i++) {
copy[i] = a[i];
}
Arrays.sort(copy, new Comparator<Integer>() { // sort it with a custom comparator
#Override
public int compare(Integer o1, Integer o2) {
int distance1 = Math.abs(value - o1);
int distance2 = Math.abs(value - o2);
return Integer.compare(distance1, distance2);
}
});
int[] answer = new int[k]; // pick the first k elements
for (int i = 0; i < answer.length; i++) {
answer[i] = copy[i];
}
return answer;
}
Related
I have made this code to rotate an array by k times. In this when I'm adding i=0 , it is showing an "ArrayOutOfBounds" exception, and when I'm changing the value of i by 1, it is showing wrong output. Why is it showing this exception? And is there any way I could correct this code?
public void rotate(int[] nums, int k)
{ int j=0, temp=0;
for(j=0;j<k;j++)
{
for(int i=0;i<nums.length;i++)
{
temp=nums[i-1];
nums[i-1]=nums[i];
nums[i]=temp;
}
}
}
}
At i=0 you are trying to access nums[i-1] = num[-1] which is an invalid position and hence an ArrayOutOfBound exception is thrown.
So, the modified version would be:
for (j=0; j<k; j++)
{
for (int i=1;i<nums.length;i++)
{
temp=nums[i-1];
nums[i-1]=nums[i];
nums[i]=temp;
}
}
But the above will rotate the array by k times towards the left not right as you are shifting the elements towards the left. So, to get the right rotation you need to shift the elements from the end of the array. Like:
for (j=0; j<k; j++)
{
for (int i=nums.length-1; 0<i; i--)
{
// shifting towards the right
temp=nums[i-1];
nums[i-1]=nums[i];
nums[i]=temp;
}
}
Edit (from comments above): If i is 0, you're trying to get an index of -1 which will raise an ArrayOutOfBounds exception. If i starts from 1, then you're not dealing with the first number.
Here's the function you can use to rotate integers to the right:
public void rotate(int[] nums, int k) {
int arrLen = nums.length;
// If the number of times you want to rotate is bigger than the size of the array, get the minimum number of rotations to get the same result.
while (k > n) {
k = k - arrLen;
}
k = arrLen - k;
k = k % arrLen;
int i, m, n, temp;
int g_c_d = gcd(k, arrLen);
// Move the value in the i-th index
for (i = 0; i < g_c_d; i++) {
temp = arr[i];
m = i;
while (true) {
n = m + k;
if (n >= arrLen) {
n = n - arrLen;
}
if (n == i) {
break;
}
arr[m] = arr[n];
m = n;
}
arr[m] = temp;
}
}
// Find the greatest common divisor of two numbers, a and b
public void gcd(int a, int b) {
if (b == 0) {
return a;
} else {
return gcd(b, a % b);
}
}
Let me briefly explain what it does. This is one of the most known algorithms: juggling. You divide the array into the n number of sets where n denotes the greatest common divisor of the length of the array and the number of times you want to rotate. Then, you move the numbers within sets.
This might be the most efficient in terms of time (as its time complexity is O(n)).
A better solution would be taking a copy of the given array with the values '0' then looping through the given array to obtain a new_index.
Formula for the New_index for the Clock-wise rotating array:
for(int i=0;i<nums.length;i++){
int new_index = (old_index+k)%(a.length)
copy[new_index] = a[old_index]
}
Now the entire function code would be:
public static void rotate(int[] a, int k)
{
int n = a.length;
int[] copy = new int[n];
// fill the values with zeroes
for(int i=0;i<n;i++){
copy[i]=0;
}
// rotate the array
for(int i=0;i<n;i++){
int new_index = (i+k)%n;
copy[new_index] = a[i];
}
// Now that the array is copied, copy the elements to the original array. Because they asked to rotate the given array.
for(int i=0;i<n;i++){
a[i]=copy[i];
}
}
function solution(arr, k) {
if(k == 0) return arr;
if(arr.length == k) return arr;
if(arr !== undefined && arr !== null){
let counter = k > arr.length ? k % arr.length : k;
let rotArray = [];
rotArray = arr.slice(arr.length - counter, arr.length).concat(arr.slice(0,arr.length - counter))
return rotArray;
}
return arr;
}
public static int[] sortArray(int[] arr) {
Arrays.sort(arr);
return arr;
}
public static int findElement(int[] arr, int x) {
int start = 0;
int end = arr.length;
int mid = 0;
while (start <= end) {
mid = (start + end)/2;
if (arr[mid] == x) {
return x;
}
else if (x <= arr[mid]) {
end = mid - 1;
}
else {
start = mid + 1;
}
}
return mid;
}
public static void printKclosest(int arr[], int x, int k)
{
int element = findElement(arr, x);
int count = 0;
for (int i = 0; i < arr.length; i++) {
int difference = Math.abs(arr[i] - element);
while (count < k) {
if (difference > 0) {
System.out.println(arr[i]);
count++;
}
}
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
int[] array = {-1, 3, 5, 2, 1, 7};
sortArray(array);
System.out.println(Arrays.toString(array));
printKclosest(array, 2, 3);
}
}
for find the k nearest elements, i was thinking I could use a for loop to go through each element in the array and subtract from the element that's X and print the number of k elements that have the smallest difference, but the output I'm getting is -1 k amount of times.
function findElement returns x value if x exists but index of potential place for x if it does not present in array.
So in the second case your comparison int difference = Math.abs(arr[i] - element); has no sense
How to overcome: change in findElement
int end = arr.length - 1;
return x;
to
return mid;
and
difference = Math.abs(arr[i] - arr[element]);
But approach to get k closest numbers is completely wrong. Suggestion:
Set L index to element and R index to element+1
Compare abs differences for L and R. Output smaller. If smaller is for R, decrement L, otherwise increment R. Repeat k times (don't forget about array range)
In addition to MBo's great suggestion for outputting the k closest elements using L and R pointers, you could also solve this without sorting the array in O(n log k) time by iterating over the array once and keeping the chosen elements in a heap, each time removing the farthest (k+1)th element.
I am trying to make radix sort function that calculates the number of digits of integer numbers using the radix sort as a base, and then sort the numbers from least significant to most significant.
I am using an array that holds random integers.
How can I make this method works well?
I am using this code:
public static void sort( int[] a, int radix)
{
int i, m = a[0], exp = 1, n = a.length;
int[] b = new int[10];
for (i = 1; i < n; i++)
if (a[i] > m)
m = a[i];
while (m / exp > 0)
{
int[] bucket = new int[10];
for (i = 0; i < n; i++)
bucket[(a[i] / exp) % 10]++;
for (i = 1; i < 10; i++)
bucket[i] += bucket[i - 1];
for (i = n - 1; i >= 0; i--)
b[--bucket[(a[i] / exp) % 10]] = a[i];
for (i = 0; i < n; i++)
a[i] = b[i];
exp *= 10;
}
}
Try
int[] b = new int[a.length];
or since n = a.length
int[] b = new int[n];
I am just pointing out the most obvious problems and leave the details to you.
Each bucket will have to hold a list of numbers so using just an int as a bucket is not going to work. Use something like this instead:
List<Integer>[] bucket = new List<Integer>[10];
The array used to collect the elements in the new order needs to be the same size as the original array. You just have made it 10 long.
Statement in last for loop
a[i] = b[i];
tells that size of b must be equal to or greater than a. Hence go for #rcgldr answer. Also the value of radix passed to your function is lying unused. You can also make your function a tad faster by swapping array pointers instead of copying the elements i.e. avoiding the last for loop.
int swap[] = a;
a = b;
b = swap;
then finally after all the loops are over, return the array a
return a;
Above is your program for sorting in ascending order. I am giving below the program to sort in descending order. The only change that was required was to start adding frequencies from the end of the base array( in this case Z ) to index zero.
public static int[] DSC(int A[], int radix, int base)
{
int length = A.length ;
int B[] = new int[length] ;
int div = 1 ;
int swap[] ;
int i ;
while(radix > 0)
{
int Z[] = new int[base] ;
i = 0 ;
while(i < length)
{
Z[( A[i] / div ) % base]++ ;
i++ ;
}
i = base ;
while(i > 1)
{
i--;
Z[i-1] += Z[i] ;
}
i = length ;
while(i > 0)
{
i-- ;
B[--Z[( A[i] / div ) % base]] = A[i];
}
swap = A;
A = B;
B = swap;
div *= base;
radix--;
}
return A;
}
For non-negative integers, using binary instead of decimal, might be more efficient & intuitive for machine.
Here is an implementation I wrote, with test case:
RadixSort.java
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/**
* Radix sort.
*
* #author eric
* #date 3/12/20 12:05 PM
*/
public class RadixSort {
/**
* Sort given array, the array will be modified.
*
* #param data array of integer of non-negative integers,
* #throws IllegalArgumentException if input contain negative integer,
*/
public static void sort(int[] data) {
int numSys = 2;
int bits = validAndfindHighestBit(data); // find highest bit,
// create queues,
List<List<Integer>> queues = new ArrayList<>(numSys);
for (int i = 0; i < numSys; i++) queues.add(new LinkedList<>());
// sort bit by bit, low to high,
for (int i = 0; i < bits; i++) {
// re-init queues,
for (int j = 0; j < numSys; j++) queues.get(j).clear();
// array -> queues,
for (int x : data) {
int bit = (x >> i) & 1; // get the i-th bit,
queues.get(bit).add(x);
}
// queues -> array,
int t = 0;
for (List<Integer> queue : queues) {
for (int x : queue) data[t++] = x;
}
}
}
/**
* Valid input number, and find highest bit that has 1.
*
* #param data
* #return
* #throws IllegalArgumentException if input contain negative integer,
*/
private static int validAndfindHighestBit(int[] data) {
// find max number,
int max = 0;
for (int x : data) {
if (x < 0) throw new IllegalArgumentException("negative integers are not supported");
if (x > max) max = x;
}
System.out.printf("max number: %d, ", max);
// find highest bit,
int highestBit = 0;
while (max != 0) {
highestBit++;
max >>= 1;
}
System.out.printf("highest bit: %d\n", highestBit);
return highestBit;
}
}
RadixSortTest.java
(Test case via TestNG)
import org.testng.Assert;
import org.testng.annotations.Test;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import static org.testng.Assert.*;
/**
* RadixSort test.
*/
public class RadixSortTest {
#Test
public void testSort() {
int[] data;
// generated un-sorted random array,
do data = genRandomArr(); while (data.length > 1 && isSorted(data));
System.out.printf("input arr:\t%s\n", Arrays.toString(data));
if (data.length > 1) Assert.assertFalse(isSorted(data));
// sort
RadixSort.sort(data);
System.out.printf("output arr:\t%s\n", Arrays.toString(data));
Assert.assertTrue(isSorted(data));
}
// corner case,
#Test
public void testSort_corner() {
int[] dataEmpty = new int[0]; // empty array,
RadixSort.sort(dataEmpty);
Assert.assertTrue(isSorted(dataEmpty));
int[] dataSingle = new int[]{5}; // single element,
RadixSort.sort(dataSingle);
Assert.assertTrue(isSorted(dataSingle));
}
// invalid input,
#Test(expectedExceptions = IllegalArgumentException.class)
public void testSort_invalid() {
int[] dataSingle = new int[]{1, -1}; // negative number,
RadixSort.sort(dataSingle);
}
/**
* generate random array, of size 10, in range [0, 1024),
*
* #return
*/
public static int[] genRandomArr() {
return genRandomArr(10, 100);
}
/**
* generate random array,
*
* #param size array size, default to 10,
* #param bound upper bound, default to 100,
* #return
*/
public static int[] genRandomArr(int size, int bound) {
if (size <= 0) size = 10;
if (bound <= 0) bound = 100;
ThreadLocalRandom rd = ThreadLocalRandom.current();
int[] arr = new int[size];
for (int i = 0; i < arr.length; i++) arr[i] = rd.nextInt(bound);
return arr;
}
// check whether array is sorted,
private static boolean isSorted(int[] a) {
for (int i = 0; i < a.length - 1; i++) {
if (a[i] > a[i + 1]) return false;
}
return true;
}
}
I want to write a method that when supplied an array of ints will do the following. For each pair of array elements it will combine them and put them into a list of an inner class objects. Then it will compare each element in the array and check if it will fit between each pair values. (i.e. I have an array 0, 2, 4 it will make for example pair (0,4) and then it will check that value 2 is indeed between 0 and 4 and so for pair (4,0). When pair (0, 2) is evaluated it won't find anything and therefore counter will increase (and so for pair (2, 0)). I have constructed the following code to evaluate number of values that indeed will fit in pairs and I hoped then to get the total number of pairs that match my need by extracting it from the total number of pairs. Now I want to optimize this query (in case I have very big arrays with thousands of members and very big or negative integers e.g. 1,000,000,000 or - 2,000,000,000). Please let me know how to do that. Mainly please focus on optimization issues thank you.
import java.util.*;
import java.util.Map;
import java.lang.*;
public class Prac1 {
public int count(int[] A){
int k = 0;
class PTemp{
int first = 0;
int second = 0;
public PTemp(int first, int second){
this.first = first;
this.second = second;
}
}
List<PTemp> r = new ArrayList<PTemp>();
int z = 0;
for (int i = 0; i < A.length; i++) {
for (int j = i+1; j < A.length; j++) {
r.add(new PTemp(A[i], A[j]));
r.add(new PTemp(A[j], A[i]));
z = z + 2;
System.out.println("["+A[i] +","+A[j]+"]");
System.out.println("["+A[j] +","+A[i]+"]");
}
}
Iterator<PTemp> ir = r.iterator();
while (ir.hasNext()){
PTemp p = ir.next();
label1:
for (int i = 0; i < A.length-1; i++){
if (((p.first < A[i]) && (A[i] < p.second)) || ((p.first > A[i]) && (A[i] > p.second))){
k = k + 1;
break label1;
}
}
}
System.out.println(z);
k = z - k;
return k;
}
public int c(int[] A) {
int z = (A.length - 1) * 2;
return z;
}
public static void main(String[] args){
int[] A = {0, 2, 2, 6, 5, 5};
Prac1 pr = new Prac1();
System.out.println(pr.count(A));
System.out.println(pr.c(A));
}
}
Without loss of generality, we can consider the array to be sorted. Assuming all numbers in the array are distinct, the pairs without elements in between are the pairs formed by neighbours. There are (array.length - 1) * 2 such pairs, i.e. you could simply do:
public int count(int[] A) {
return (A.length - 1) * 2;
}
If the array may contain duplicates, you should specify how they are to be counted.
Sort the array. Make a single pass over the array, identifying groups of equal elements. For each such group, multiply the number of elements in the group, the number of smaller elements, and the number of larger elements. Add that to a running count.
public int count(int[] A) {
int i = 0, k = 0, j = 0;
Arrays.sort(A); // you need to import java.util.Arrays
while(i < A.length) {
for(j = i+1; j < A.length && A[j] == A[i]; j++);
k += (j - i) * i * (A.length - j);
i = j;
}
return k;
}
I'm trying to make an implementation of 'adding' the elements of two arrays in Java.
I have two arrays which contain integers and i wanna add them. I dont want to use immutable variables. I prefer do sth like that : a.plus(b);
The problem is when i add 2 arrays with different length.It tries to add the elements of b to a, but if b has a bigger length it flags an error "ArrayIndexOutOfBoundsException".
I can understand why that's happening. But how can i solve this?
How can i expand array a? :/
public void plus(int[] b)
{
int maxlength = Math.max( this.length, b.length );
if (maxlength==a.length)
{
for (int i = 0; i <= maxlength; i++)
{
a[i] = a[i] + b[i]; //ArrayIndexOutOfBoundsException error
}
}
}
i <= maxlength replace this with i < maxlength.
Your array index is starting at zero, not at one.
So the length of the array is one less than the end index of the array.
When you use <= you are trying to go one element after the last element in your array, Hence the exception.
Also you got to check the length of array b. If length of array b is smaller than a, you will end up facing the same exception.
int maxlength = Math.min( this.length, b.length ); is more appropriate.
Or incase if you don't want to miss out any elements in either of the arrays while adding, ArrayList is the answer for you. ArrayList is the self expanding array you are looking for.
Here is how you can do that -
// First ArrayList
ArrayList<Integer> a = new ArrayList<Integer>();
a.add(1);
a.add(2);
a.add(3);
// Second ArrayList
ArrayList<Integer> b = new ArrayList<Integer>();
b.add(1);
b.add(2);
b.add(3);
b.add(4);
int maxlength = Math.max(a.size(), b.size());
// Add the elements and put them in the first ArrayList in the corresponding
// position
for (int i = 0; i < maxlength; i++) {
if (i < a.size()) {
if (i < b.size()) {
int j = a.get(i);
a.set(i, j + b.get(i));
}
} else {
a.add(i, b.get(i));
}
}
for (int j : a) {
System.out.println(j);
}
How can i expand array a?
Don't use arrays if you need variable-size data structures. Use Lists.
How about this:
private int[] a;
/**
* Adds the specified array to our array, element by element, i.e.
* for index i, a[i] = a[i] + b[i]. If the incoming array is
* longer, we pad our array with 0's to match the length of b[].
* If our array is longer, then only the first [b.length] values
* of our array have b[] values added to them (which is the same
* as if b[] were padded with 0's to match the length of a[].
*
* #param b the array to add, may not be null
*/
public void plus(final int[] b)
{
assert b != null;
if (a.length < b.length) {
// Expand a to match b
// Have to move a to a larger array, no way to increase its
// length "dynamically", i.e. in place.
final int[] newA = new int[b.length];
System.arraycopy(a, 0, newA, 0, a.length);
// remaining new elements of newA default to 0
a = newA;
}
for (int i = 0; i < b.length; i++)
{
a[i] = a[i] + b[i];
}
}
Another version:
private ArrayList<Integer> aList;
public void plusList(final int[] b)
{
assert b != null;
if (aList.size() < b.length) {
aList.ensureCapacity(b.length);
}
for (int i = 0; i < b.length; i++)
{
if (i < aList.size()) {
aList.set(i, aList.get(i) + b[i]);
} else {
aList.add(b[i]);
}
}
}
Edit: Here's the full class with sample run from data in comments
public class AddableArray {
private int[] a;
public AddableArray(final int... a) {
this.a = a;
}
/**
* Adds the specified array to our array, element by element, i.e.
* for index i, a[i] = a[i] + b[i]. If the incoming array is
* longer, we pad our array with 0's to match the length of b[].
* If our array is longer, then only the first [b.length] values
* of our array have b[] values added to them (which is the same
* as if b[] were padded with 0's to match the length of a[].
*
* #param b the array to add, may not be null
*/
public void plus(final int[] b)
{
assert b != null;
if (a.length < b.length) {
// Expand a to match b
// Have to move a to a larger array, no way to increase its
// length "dynamically", i.e. in place.
final int[] newA = new int[b.length];
System.arraycopy(a, 0, newA, 0, a.length);
// remaining new elements of newA default to 0
a = newA;
}
for (int i = 0; i < b.length; i++)
{
a[i] = a[i] + b[i];
}
}
int[] get() {
return a;
}
#Override
public String toString() {
final StringBuilder sb = new StringBuilder("a[] = [ ");
for (int i = 0; i < a.length; i++) {
if (i > 0) sb.append(", ");
sb.append(a[i]);
}
sb.append(" ]");
return sb.toString();
}
public static void main (final String[] args) {
final AddableArray myAddableArray = new AddableArray(1,2,3);
System.out.println("Elements before plus(): ");
System.out.println(myAddableArray.toString());
final int b[]={1,2,3,4};
myAddableArray.plus(b);
System.out.println("Elements after plus(): ");
System.out.println(myAddableArray.toString());
}
}
Sample run:
Elements before plus():
a[] = [ 1, 2, 3 ]
Elements after plus():
a[] = [ 2, 4, 6, 4 ]
maxlength is the max between the size of a[] and b[], so in a loop from 0 to maxlength, you will get an ArrayIndexOutOfBoundsException when i exceeds the min of the size of a[] and b[].
Try this:
public void plus(int[] b)
{
Polynomial a = this;
int[] c;
int maxlength;
if (a.length>b.length) {
c=a;
maxlength=a.length;
} else {
c=b;
maxlength=b.length;
}
int ca, cb;
for (int i = 0; i < maxlength; i++)
{
if (i<this.length)
ca=a[i];
else
ca=0;
if (i<b.length)
cb=b[i];
else
cb=0;
c[i] = ca + cb;
}
}
Try replacing:
for (int i = 0; i <= maxlength; i++)
with:
for (int i = 0; i < maxlength; i++)