binary search keeps returning element not present // - java

I tried to create the algorithm as practice, but I'm not too sure as for where I blundered but I keep getting "Element not present" even if the array is sorted.//
I'm trying to create random arrays and sort it at the same time. Meanwhile, I want to see how many comparisons it takes, and also measure how much time it takes for this program to run in (ms).
Some problems at the moment:
Keeps printing: Element not present, and time as 0. I know binary is time efficient, but I'm kind of sketchy with this being at 0/ or at 1 to 2 in many cases when the x is at 5000 or a million to 20 million. I think that should take some time still.
//main
import java.util.Arrays;
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author temur
*/
public class main {
public static int[] randomIntArray(int n, int low, int high) {
// Set up for generating random numbers
int range = high - low + 1;
int shift = low;
int[] arr = new int[n];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) (Math.random() * range) + shift;
}
return arr;
}
public static boolean isSorted(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
if (arr[i] > arr[i + 1]) {
return false;
}
}
return true;
}
public static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void print(int[] arr) {
System.out.println(java.util.Arrays.toString(arr));
}
//____________________________________________________________
public static void main(String[] args) {
binary ob = new binary();
int[] arr = randomIntArray(1, 20000000, 20000000);
Arrays.sort(arr);
int x = 55432;
int n = 1;
long startTime = System.currentTimeMillis();
int result = ob.binarySearch(arr, 0, n - 1, x);
System.out.println(
"Element in evaluation: " + x);
if (result
== -1) {
System.out.println("Element not present");
} else {
System.out.println("Element found at index: "
+ result);
}
System.out.println(
"Ammount of comparisons: " + ob.count);
long endTime = System.currentTimeMillis();
System.out.println("Time (ms):"+ (endTime - startTime));
}
}
//binary
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author temur
*/
public class binary {
int count = 0;
int binarySearch(int arr[], int l, int r, int x) {
count += 1;
if (r >= l) {
int mid = l + (r - l) / 2;
if (arr[mid] == x) {
return mid;
}
if (arr[mid] > x) {
return binarySearch(arr, l, mid - 1, x);
}
return binarySearch(arr, mid + 1, r, x);
}
return -1;
}
}

You are making an array 1 element long, with elements randomly generated between 20000000 and 20000000. In other words, it's always {20000000}. Of course 55432 isn't going to be in that array, and the binary search is going to figure that out pretty fast.

It is simple that your randomIntArray with values you pass is going to give single length array.
Run Code:
int[] arr = randomIntArray(1, 20000000, 20000000);
System.out.println("Array "+Arrays.toString(arr));
Output:
Array [20000000]
so the value 55432 is not present in this array and that is a very fast to figure it out.

Related

Parallel implementation of bubble sort

The main idea of this project is to parallel bubble sort. my approach to this project is,to create one big array and then divide it in to parts ( 4 or 5) based on the number of threads. for instance if the size of the array is 10, i divide it into 2 sub arrays, 0-4 and 5-9, then one thread has to scan the big arrays, and if the value is between 0-4 , assign the the the first sub arrays, if not assign to the next sub-array. then apple the bubble sort algorithm to all sub-arrays simultaneously. finally, all the sub arrays should be added to a thread safe queue.
for now i have three class, the main class where i created the array, the U tiles class for shuffling the array, find the min and max of the array and the bubble sort class that has a bubble sorting algorithms.
my challenge for now is, how divide the big array into small sub-arrays and fill the sub-array with values.
i will appreciate all suggestions and helps. under is my classes.
package com.company;
import javax.xml.transform.sax.SAXSource;
import java.util.Random;
public class Main {
public static void main(String[] args) {
// filling the array with integer values
int[] anArray = Utils.fillArray((int) 10);
Utils.shuffleArray(anArray);
// find the min and max of the array
System.out.println("************************");
BubbleSort sort = new BubbleSort(anArray);
profiler.start();
sort.sortMethod();
// Utils.printArray(anArray);
Utils.findMinMax(anArray);
}
}
package com.company;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
public class Utils {
private static volatile int max;
private static volatile int min;
private static int[][] arrays;
public Utils(int[][] arrays,int[] array) {
max = array[0];
min = array[0];
}
// taken from the kings class
// source: http://stackoverflow.com/questions/1519736/random-shuffling-of-an-array
// Implementing Fisher�Yates shuffle
public static void shuffleArray(int[] ar) {
// If running on Java 6 or older, use `new Random()` on RHS here
ThreadLocalRandom rnd = ThreadLocalRandom.current();
for (int i = ar.length - 1; i > 0; i--) {
int index = rnd.nextInt(i + 1);
// Simple swap
int a = ar[index];
ar[index] = ar[i];
ar[i] = a;
}
}
public static void printArray(int[] anArray) {
System.out.print("Array: ");
for (int i=0; i< anArray.length; i++){
System.out.print(anArray[i]+" ");
}
System.out.println();
}
public static int[] fillArray(int amount) {
int[] result = new int[amount];
for (int i=0; i<amount; i++){
result[i] = i;
}
return result;
}
public static void findMinMax(int[] array) {
int i = 0;
for (; i < (array.length) / 2; i++) {
int num1 = array[1 * 2];
int num2 = array[i * 2 + 1];
if (num1 >= num2) {
if (num1 > max)
max = num1;
if (num2 < min)
min = num2;
} else {
if (num2 > max) {
max = num2;
if (num1 < min)
min = num1;
}
}
}
if (i * 2 < array.length) {
int num = array[i * 2];
if (num > max)
max = num;
if (num < min)
min = num;
}
System.out.println("min is: " + min);
System.out.println("max is : " + max);
}
}
public static int getMax() {
return max;
}
public static int getMin() {
return min;
}
public static void print(int[] anArray, int i) {
}
}
I think you should try merge sort, using Fork/Join.
Like here:
import java.util.Random;
import java.util.concurrent.*;
/**
* Example of Merge Sort using Fork/Join framework.
*
* #author L.Gobinath
*/
public class ForkJoinArraySort {
// From Java 7 '_' can be used to separate digits.
public static final int ARRAY_SIZE = 10_000_000;
public static void main(String[] args) {
// Create a pool of threads
ForkJoinPool pool = new ForkJoinPool();
int[] array = createArray(ARRAY_SIZE);
long startTime;
long endTime;
MergeSort mergeSort = new MergeSort(array, 0, array.length - 1);
startTime = System.currentTimeMillis();
pool.invoke(mergeSort); // Start execution and wait for result/return
endTime = System.currentTimeMillis();
System.out.println("Time taken: " + (endTime - startTime) + " millis");
}
/**
* Create an array with random numbers.
* #param size Size of the array.
* #return An array with the given size.
*/
private static int[] createArray(final int size) {
int[] array = new int[size];
Random rand = new Random();
for (int i = 0; i < size; i++) {
array[i] = rand.nextInt(1000);
}
return array;
}
}
/**
* Extends RecursiveAction.
* Notice that the compute method does not return anything.
*/
class MergeSort extends RecursiveAction {
private int array[];
private int left;
private int right;
public MergeSort(int[] array, int left, int right) {
this.array = array;
this.left = left;
this.right = right;
}
/**
* Inherited from RecursiveAction.
* Compare it with the run method of a Thread.
*/
#Override
protected void compute() {
if (left < right) {
int mid = (left + right) / 2;
RecursiveAction leftSort = new MergeSort(array, left, mid);
RecursiveAction rightSort = new MergeSort(array, mid + 1, right);
invokeAll(leftSort, rightSort);
merge(left, mid, right);
}
}
/**
* Merge two parts of an array in sorted manner.
* #param left Left side of left array.
* #param mid Middle of separation.
* #param right Right side of right array.
*/
private void merge(int left, int mid, int right) {
int temp [] = new int[right - left + 1];
int x = left;
int y = mid + 1;
int z = 0;
//There some kind of sort at the leaf
//You can use your BubbleSort class
//***************************************************************
while (x <= mid && y <= right) {
if (array[x] <= array[y]) {
temp[z] = array[x];
z++;
x++;
} else {
temp[z] = array[y];
z++;
y++;
}
}
//***************************************************************
while (y <= right) {
temp[z++] = array[y++];
}
while (x <= mid) {
temp[z++] = array[x++];
}
for (z = 0; z < temp.length; z++) {
array[left + z] = temp[z];
}
}
}
(I had my own algorithm, where I used merge sorting, and in the leaf nodes sorting with a bubble sort when I studied algorithmization. But it was a long time ago, I lost it, sorry.)
P.S. I think it will be superfluous to recall that Array.sort will still be faster than the personal implementation of bubble sorting.

time complexity - Binary Indexed Tree

I am writing a binary indexed tree. As documentation, it requires nlogn time to pre process. But I am not able to understand why.
In my case I am constructing the tree from the Array, which should take 2n time, as first time traversing the array once to make it a Binary tree and then to update sum I am again traversing the tree in POST order fashion. so total 2n, not nlogn.
Can anybody explain why it needs nlogn time to pre-process the binary indexed tree.
public class BITree {
private class BTN {
int data;
int index;
BTN left,right;
public BTN(int data) {
this.data = data;
}
}
BTN head = null;
public BTN toBT(int[] arr,int start,int end){
if(start <= end){
int mid = start + (end - start)/2;
BTN btn = new BTN(arr[mid]);
btn.index = mid+1;
btn.left = toBT(arr,start,mid-1);
btn.right = toBT(arr,mid+1,end);
return btn;
}
return null;
}
public int sumAtIndex(BTN btn,int index){
int sum = 0;
if(index < btn.index)
sum += sumAtIndex(btn.left,index);
else if(index > btn.index) {
sum += btn.data + sumAtIndex(btn.right, index);
}
if(btn.index == index)
return btn.data + sum;
return sum;
}
public int replaceSum(BTN btn){
if(btn == null){
return 0;
}
int l = replaceSum(btn.left);
int r = replaceSum(btn.right);
int sum = btn.data + l + r;
btn.data += l;
return sum;
}
void inOrder(BTN btn){
if(btn != null) {
inOrder(btn.left);
System.out.print((btn.index+":"+btn.data)+",");
inOrder(btn.right);
}
}
public static void main(String[] args) {
int[] arr = {5,1,6,4,2,3,3};
BITree s2 = new BITree();
BTN btn = s2.toBT(arr,0,arr.length-1);
s2.replaceSum(btn);
s2.inOrder(btn);
System.out.println();
System.out.println(s2.sumAtIndex(btn,3));
}
}
This question is a duplicate of :Is it possible to build a Fenwick tree in O(n)?
#Thilo , Thanks for pointing out the optimized way for preprocessing the the BIT. Which can be done in O(n) time.
https://en.wikipedia.org/wiki/Talk:Fenwick_tree
https://stackoverflow.com/a/31070683/3080158
#SanketMakani, Thanks for sharing the link, it explains the BIT very well.
here is the working code, with O(n) pre processing time.
package com.rabin;
import java.util.StringJoiner;
/**
*
*/
public class BITree {
/**
* O(logn)
* #param arr
* #param index
* #param val
*/
void update(int arr[],int index, int val)
{
index++;
for(; index <= arr.length-1; index += index&-index)
arr[index] += val;
}
/**
* O(logn)
* #param arr
* #param noOfElements
* #return
*/
int query(int[] arr,int noOfElements)
{
int sum = 0;
for(; noOfElements > 0; noOfElements -= noOfElements&-noOfElements)
sum += arr[noOfElements-1];
return sum;
}
/**
* O(n)
* #param arr
*/
void toBIT(int[] arr){
int n = arr.length;
for(int i=1;i<=n;i++){
int j = i+ (i & -i);
if(j <= n)
arr[j-1] += arr[i-1];
}
}
static String arrayToString(int[] arr){
StringJoiner sj = new StringJoiner(",","[","]");
for(int i = 0; i< arr.length ;i++){
sj.add(String.valueOf(arr[i]));
}
return sj.toString();
}
public static void main(String[] args) {
int[] arr = {5,1,6,4,2,3,3};
BITree bit = new BITree();
System.out.println("Original Array:" +arrayToString(arr));
bit.toBIT(arr);
System.out.println("BIT Array:" +arrayToString(arr));
System.out.println("Sum of first 5 nos : "+ bit.query(arr,5));
bit.update(arr,0,8);
System.out.println("Sum of first 5 nos after update : "+ bit.query(arr,5));
}
}
#RBanerjee nicely written code, It is good to implement the BIT with one additional index, which helps in code comprehension. Plus it also signifies one additional thing - the least significant 1 bit from the BIT index indicates as to how many elements does the particular index stores. For e.g. index = 2 (010) can signify index 2 in BIT holds the values of 2 elements, similarly 4 (100) for 4, 6 (110) stores 2 values (namely, index 5 and 6) and so on.
Additionally, in your update method you aren't updating the value per se. You are adding the given value. Which I do not think signifies the meaning of update. It is a very subjective discussion, but I think of it as an update and not an increment. So, if the index 5 originally holds value 2, and when I want to update it to -1, it means the value after the update at index 5 is -1 and not 1.
As an extra step, it is good to provide a way to query the ranges in the array. For e.g. what is the value between indices 2 and 5 (inclusive).
<!-- language: java -->
package DataStructureImplementation;
import java.util.StringJoiner;
public class BinaryIndexedTree {
private final int[] bit;
private final int[] nums;
private final int n;
public BinaryIndexedTree(int[] nums) {
n = nums.length;
bit = new int[n + 1];
this.nums = nums;
System.arraycopy(nums, 0, bit, 1, nums.length);
build();
}
/**
* Builds a binary indexed tree in O(n) time.
*/
private void build() {
int j;
for (int i = 1; i <= n; ++i) {
j = i + (i & -i);
if (j <= n) bit[j] += bit[i];
}
}
/**
* Updates an indexed item in the original array to the given value.
* Also updates the values in the 'BIT' in O(logn) time.
* #param index - index of the item to update
* #param value - value to update to
*/
public void update(int index, int value) {
int diff = value - nums[index];
nums[index] = value;
index++;
while (index <= n) {
bit[index] += diff;
index += (index & -index);
}
}
/**
* Queries the sum of the first 'K' indices in the original array in O(logn) time.
* #param k - the number of items to aggregate.
* #return - the sum of first 'K' numbers in the original array.
* #throws Exception - if 'K' is out of bounds.
*/
public int query(int k) throws Exception {
if (k < 0 || k > n) throw new Exception("Invalid query range : " + k);
int sum = 0;
while (k > 0) {
sum += bit[k];
k -= (k & -k);
}
return sum;
}
/**
* Queries the sum of numbers from the original array between index1 and index2 (inclusive) in O(logn) time.
* #param index1 - left index.
* #param index2 - right index.
* #return - the sum of numbers between the given ranges.
* #throws Exception - if range is out of bounds.
*/
public int queryRange(int index1, int index2) throws Exception {
return query(index2 + 1) - query(index1);
}
/**
* Helper method to print the array contents.
* #param nums - the array to print.
* #return - the contents of the array as string.
*/
static String arrayToString(int[] nums){
StringJoiner stringJoiner = new StringJoiner(",","[","]");
for (int n : nums) {
stringJoiner.add(String.valueOf(n));
}
return stringJoiner.toString();
}
public static void main(String[] args) throws Exception {
int[] nums = {5,8,5,4,2,3};
BinaryIndexedTree binaryIndexedTree = new BinaryIndexedTree(nums);
System.out.println("Original Array : " + arrayToString(nums));
System.out.println("BIT Array : " + arrayToString(binaryIndexedTree.bit));
System.out.println("Sum of first 5 nos : " + binaryIndexedTree.query(5));
binaryIndexedTree.update(4,-1);
System.out.println("Original Array after update : " + arrayToString(nums));
System.out.println("BIT Array after update : " + arrayToString(binaryIndexedTree.bit));
System.out.println("Sum of first 5 nos after update : " + binaryIndexedTree.query(5));
System.out.println("Sum of numbers in range 2-5 : " + binaryIndexedTree.queryRange(2, 5));
}
}

Dynamic programming approach to TSP in Java

I'm a beginner, and I'm trying to write a working travelling salesman problem using dynamic programming approach.
This is the code for my compute function:
public static int compute(int[] unvisitedSet, int dest) {
if (unvisitedSet.length == 1)
return distMtx[dest][unvisitedSet[0]];
int[] newSet = new int[unvisitedSet.length-1];
int distMin = Integer.MAX_VALUE;
for (int i = 0; i < unvisitedSet.length; i++) {
for (int j = 0; j < newSet.length; j++) {
if (j < i) newSet[j] = unvisitedSet[j];
else newSet[j] = unvisitedSet[j+1];
}
int distCur;
if (distMtx[dest][unvisitedSet[i]] != -1) {
distCur = compute(newSet, unvisitedSet[i]) + distMtx[unvisitedSet[i]][dest];
if (distMin > distCur)
distMin = distCur;
}
else {
System.out.println("No path between " + dest + " and " + unvisitedSet[i]);
}
}
return distMin;
}
The code is not giving me the correct answers, and I'm trying to figure out where the error is occurring. I think my error occurs when I add:
distCur = compute(newSet, unvisitedSet[i]) + distMtx[unvisitedSet[i]][dest];
So I've been messing around with that part, moving the addition to the very end right before I return distMin and so on... But I couldn't figure it out.
Although I'm sure it can be inferred from the code, I will state the following facts to clarify.
distMtx stores all the intercity distances, and distances are symmetric, meaning if distance from city A to city B is 3, then the distance from city B to city A is also 3. Also, if two cities don't have any direct paths, the distance value is -1.
Any help would be very much appreciated!
Thanks!
Edit:
The main function reads the intercity distances from a text file. Because I'm assuming the number of cities will always be less than 100, global int variable distMtx is [100][100].
Once the matrix is filled with the necessary information, an array of all the cities are created. The names of the cities are basically numbers. So if I have 4 cities, set[4] = {0, 1, 2, 3}.
In the main function, after distMtx and set is created, first call to compute() is called:
int optRoute = compute(set, 0);
System.out.println(optRoute);
Sample input:
-1 3 2 7
3 -1 10 1
2 10 -1 4
7 1 4 -1
Expected output:
10
Here's a working iterative solution to the TSP with dynamic programming. What would make your life easier is to store the current state as a bitmask instead of in an array. This has the advantage that the state representation is compact and can be cached easily.
I made a video detailing the solution to this problem on Youtube, please enjoy! Code was taken from my github repo
/**
* An implementation of the traveling salesman problem in Java using dynamic
* programming to improve the time complexity from O(n!) to O(n^2 * 2^n).
*
* Time Complexity: O(n^2 * 2^n)
* Space Complexity: O(n * 2^n)
*
**/
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
public class TspDynamicProgrammingIterative {
private final int N, start;
private final double[][] distance;
private List<Integer> tour = new ArrayList<>();
private double minTourCost = Double.POSITIVE_INFINITY;
private boolean ranSolver = false;
public TspDynamicProgrammingIterative(double[][] distance) {
this(0, distance);
}
public TspDynamicProgrammingIterative(int start, double[][] distance) {
N = distance.length;
if (N <= 2) throw new IllegalStateException("N <= 2 not yet supported.");
if (N != distance[0].length) throw new IllegalStateException("Matrix must be square (n x n)");
if (start < 0 || start >= N) throw new IllegalArgumentException("Invalid start node.");
this.start = start;
this.distance = distance;
}
// Returns the optimal tour for the traveling salesman problem.
public List<Integer> getTour() {
if (!ranSolver) solve();
return tour;
}
// Returns the minimal tour cost.
public double getTourCost() {
if (!ranSolver) solve();
return minTourCost;
}
// Solves the traveling salesman problem and caches solution.
public void solve() {
if (ranSolver) return;
final int END_STATE = (1 << N) - 1;
Double[][] memo = new Double[N][1 << N];
// Add all outgoing edges from the starting node to memo table.
for (int end = 0; end < N; end++) {
if (end == start) continue;
memo[end][(1 << start) | (1 << end)] = distance[start][end];
}
for (int r = 3; r <= N; r++) {
for (int subset : combinations(r, N)) {
if (notIn(start, subset)) continue;
for (int next = 0; next < N; next++) {
if (next == start || notIn(next, subset)) continue;
int subsetWithoutNext = subset ^ (1 << next);
double minDist = Double.POSITIVE_INFINITY;
for (int end = 0; end < N; end++) {
if (end == start || end == next || notIn(end, subset)) continue;
double newDistance = memo[end][subsetWithoutNext] + distance[end][next];
if (newDistance < minDist) {
minDist = newDistance;
}
}
memo[next][subset] = minDist;
}
}
}
// Connect tour back to starting node and minimize cost.
for (int i = 0; i < N; i++) {
if (i == start) continue;
double tourCost = memo[i][END_STATE] + distance[i][start];
if (tourCost < minTourCost) {
minTourCost = tourCost;
}
}
int lastIndex = start;
int state = END_STATE;
tour.add(start);
// Reconstruct TSP path from memo table.
for (int i = 1; i < N; i++) {
int index = -1;
for (int j = 0; j < N; j++) {
if (j == start || notIn(j, state)) continue;
if (index == -1) index = j;
double prevDist = memo[index][state] + distance[index][lastIndex];
double newDist = memo[j][state] + distance[j][lastIndex];
if (newDist < prevDist) {
index = j;
}
}
tour.add(index);
state = state ^ (1 << index);
lastIndex = index;
}
tour.add(start);
Collections.reverse(tour);
ranSolver = true;
}
private static boolean notIn(int elem, int subset) {
return ((1 << elem) & subset) == 0;
}
// This method generates all bit sets of size n where r bits
// are set to one. The result is returned as a list of integer masks.
public static List<Integer> combinations(int r, int n) {
List<Integer> subsets = new ArrayList<>();
combinations(0, 0, r, n, subsets);
return subsets;
}
// To find all the combinations of size r we need to recurse until we have
// selected r elements (aka r = 0), otherwise if r != 0 then we still need to select
// an element which is found after the position of our last selected element
private static void combinations(int set, int at, int r, int n, List<Integer> subsets) {
// Return early if there are more elements left to select than what is available.
int elementsLeftToPick = n - at;
if (elementsLeftToPick < r) return;
// We selected 'r' elements so we found a valid subset!
if (r == 0) {
subsets.add(set);
} else {
for (int i = at; i < n; i++) {
// Try including this element
set |= 1 << i;
combinations(set, i + 1, r - 1, n, subsets);
// Backtrack and try the instance where we did not include this element
set &= ~(1 << i);
}
}
}
public static void main(String[] args) {
// Create adjacency matrix
int n = 6;
double[][] distanceMatrix = new double[n][n];
for (double[] row : distanceMatrix) java.util.Arrays.fill(row, 10000);
distanceMatrix[5][0] = 10;
distanceMatrix[1][5] = 12;
distanceMatrix[4][1] = 2;
distanceMatrix[2][4] = 4;
distanceMatrix[3][2] = 6;
distanceMatrix[0][3] = 8;
int startNode = 0;
TspDynamicProgrammingIterative solver = new TspDynamicProgrammingIterative(startNode, distanceMatrix);
// Prints: [0, 3, 2, 4, 1, 5, 0]
System.out.println("Tour: " + solver.getTour());
// Print: 42.0
System.out.println("Tour cost: " + solver.getTourCost());
}
}
I know this is pretty old question but it might help somebody in the future.
Here is very well written paper on TSP with dynamic programming approach
https://github.com/evandrix/SPOJ/blob/master/DP_Main112/Solving-Traveling-Salesman-Problem-by-Dynamic-Programming-Approach-in-Java.pdf
I think you have to make some changes in your program.
Here there is an implementation
http://www.sanfoundry.com/java-program-implement-traveling-salesman-problem-using-nearest-neighbour-algorithm/

Generating vampire numbers in free range

I am writing program which generates Vampire numbers https://en.wikipedia.org/wiki/Vampire_number.
I have main function with numberOfDigits argument, which must be even. If numberOfDigits is equal 4, then we are searching Vampire Numbers in range 1000 to 9999 - four digits. If numberOfDigits is equal 6, then we are searching Vampire Numbers from 100000 to 999999 - which is six digits.
In following file, when I want to search Vampire numbers in range of 10 digits, Java heap space is screaming. Note that I have default settings for memory. But for, numberOfDigits == 4, 6 or 8, code is working correctly. (compared output to https://oeis.org/A014575/b014575.txt , https://oeis.org/A014575 ). So I want to ask,
What I can do to optimize this code? I have thought about using String with digits inside, instead of long/BigInteger. I want to "omit" that heap problem. Saving big numbers to file would be too slow, am I right?
My mate wrote (bigNum.cpp) http://pastebin.com/0HHdE848 - class in C++, to operate on big numbers. Maybe with help from community I could implement that in my a.java? More important - would it be useful for my problem?
edit: My goal is to generate free range of Vampire Numbers, like 4,6,8 - a.java it can do it, even more (if I can bypass heap space problem). And that is when my questions to help comes.
a.java (permutation code from johk95, https://stackoverflow.com/a/20906510 )
import java.util.ArrayList;
import java.util.Arrays;
/**
*
* #author re
*/
public class a {
/**
*
* #param numberOfDigits {int}
* #return ArrayList of Integer
*/
public ArrayList<Integer> vdf(int numberOfDigits) {
if ((numberOfDigits % 2) == 1) {
//or throw Exception of unrecognised format/variable?
System.out.println("cant operate on odd argument");
return new ArrayList<>();
}
long maxRange = 9;
for (int i = 1; i < numberOfDigits; i++) {
maxRange *= 10;
maxRange += 9;
}//numberOfDigits==4 then maxRange==9999, nOD==5 then maxRange==99999,..
long minRange = 1;
for (int i = 1; i < numberOfDigits; i++) {
minRange *= 10;
}//nOD==4 then minRange==1000, nOD==5 then minRange==10000, ..
ArrayList<Integer> ret = new ArrayList<>();
for (long i = minRange; i < maxRange; i++) {
long a = i;
long[] b = new long[numberOfDigits];
for (int j = numberOfDigits-1; j >= 0 ; j--) {
long c = a % 10;
a = a / 10;
b[j] = c;
}
int x = 0;
int y = 0;
ArrayList<long[]> list = permutations(b);
b = null; //dont need now
for(long[] s : list) {
for (int j = 0; j < numberOfDigits/2; j++) {
x += s[(numberOfDigits/2)-j-1] * Math.pow(10, j);
y += s[numberOfDigits-j-1] * Math.pow(10, j);
}
StringBuilder builder = new StringBuilder();
for (long t : s) {
builder.append(t);
}
String v = builder.toString();
if ((v.charAt((v.length()/2)-1) != '0'||
v.charAt(v.length()-1) != '0') &&
x * y == i) {
ret.add(x);
ret.add(y);
System.out.println(x*y+" "+x+" "+y);
break;
}
x = y = 0;
}
}
System.out.printf("%d vampire numbers found\n", ret.size()/2);
return ret;
}
/**
*
*#return vdf(4)
*/
public ArrayList<Integer> vdf() {
return vdf(4);//without trailing zeros
}
/* permutation code copied from
* johk95
* https://stackoverflow.com/a/20906510
*/
private static ArrayList<long[]> permutations(long[] lol) {
ArrayList<long[]> ret = new ArrayList<>();
permutation(lol, 0, ret);
return ret;
}
private static void permutation(long[] arr, int pos, ArrayList<long[]> list){
if(arr.length - pos == 1)
list.add(arr.clone());
else
for(int i = pos; i < arr.length; i++){
swap(arr, pos, i);
permutation(arr, pos+1, list);
swap(arr, pos, i);
}
}
private static void swap(long[] arr, int pos1, int pos2){
long h = arr[pos1];
arr[pos1] = arr[pos2];
arr[pos2] = h;
}
public static void main(String[] args) {
a a = new a();
try{
a.vdf(10); //TRY IT WITH 4, 6 or 8. <<<<
}catch (java.lang.OutOfMemoryError e){
System.err.println(e.getMessage());
}
}
}
EDIT: http://ideone.com/3rHhep - working code above with numberOfDigits == 4.
package testing;
import java.util.Arrays;
public class Testing
{
final static int START = 11, END = 1000;
public static void main(String[] args)
{
char[] kChar, checkChar;
String kStr, checkStr;
int k;
for(int i=START; i<END; i++) {
for(int i1=i; i1<100; i1++) {
k = i * i1;
kStr = Integer.toString(k);
checkStr = Integer.toString(i) + Integer.toString(i1);
//if(kStr.length() != 4) break;
kChar = kStr.toCharArray();
checkChar = checkStr.toCharArray();
Arrays.sort(kChar);
Arrays.sort(checkChar);
if(Arrays.equals(kChar, checkChar)) {
System.out.println(i + " * " + i1 + " = " + k);
}
}
}
}
}
This will generate vampire numbers, just modify the start and end integers.

time limit exceeded on java code of UVA 11516 Wifi

I am wondering why my code keeps having this "time limit exceed" on the uva-online judge page (http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2511), it is supposed to execute in 1 second but I don't know which input they use (my code works and do exactly what it supposed).. I am wondering that maybe the while loop of the testCases have something to do, because when I remove it it says wrong answer.. this is my code:
public class Main {
private static final int TAM = 10000; // TAM equals to the posible numbers of houses
private static int[] auxHouses;
private static int nHouses[];
private static int testCases;
private static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
nHouses = new int[TAM];
// First we read the input
// Read the variable of testCases
testCases = scanner.nextInt();
while (testCases > 0) {
float sol = binarySearch(testCases);
System.out.println(sol);
testCases--;
}
}
public static float binarySearch(int tC) {
int routers = 0, houses = 0;
int pivot = 0;
int hi = 0;
// While for the testCases
routers = scanner.nextInt();
houses = scanner.nextInt();
// Read the numbers of the houses
for (int i = 0; i < houses; i++) {
nHouses[i] = scanner.nextInt();
}
if (routers >= houses) {
return 0;
}
// First we sort the array
sortHouses(nHouses, houses);
// Prepare the variables of the index
int lo = 0;
hi = 2 * (nHouses[houses - 1] - nHouses[0] + 1); // 2*(loc[h-1]-loc[0]+1);
// Now we execute the binary search algorithm
while (hi > lo) {
pivot = (lo + hi) / 2;
int start = nHouses[0];
int need = 1;
for (int i = 0; i < houses; i++) {
if (nHouses[i] > start + pivot) {
start = nHouses[i];
need++;
}
}
if (need > routers) {
lo = pivot + 1;
} else {
hi = pivot;
}
}
return (float) hi / 2;
}
public static void sortHouses(int[] nhouses, int length) {
// First we check if the are actually values on the array
if (nhouses.length == 0) {
return;
}
// Copy the array of int into an auxiliary variable and the numbers of
// int in the array
auxHouses = nhouses;
int lengthArray = length;
quickSort(0, lengthArray - 1);
}
public static void quickSort(int low, int high) {
// System.out.println("Array " + Arrays.toString(auxHouses));
int i = low, j = high;
// Get the pivot element from the middle of the list
int pivot = auxHouses[low + (high - low) / 2];
// Divide into two lists
while (i <= j) {
// If the current value from the left list is smaller then the pivot
// element then get the next element from the left list
while (auxHouses[i] < pivot) {
i++;
}
// If the current value from the right list is larger then the pivot
// element then get the next element from the right list
while (auxHouses[j] > pivot) {
j--;
}
// If we have found a values in the left list which is larger then
// the pivot element and if we have found a value in the right list
// which is smaller then the pivot element then we exchange the
// values.
// As we are done we can increase i and j
if (i <= j) {
exchange(i, j);
i++;
j--;
}
}
// Recursion
if (low < j)
quickSort(low, j);
if (i < high)
quickSort(i, high);
}
private static void exchange(int i, int j) {
int temp = auxHouses[i];
auxHouses[i] = auxHouses[j];
auxHouses[j] = temp;
}
}
I have it with the quicksort implemented, but if you use Arrays.sort(..) method instead it says the same thing..TLE, what could be doing wrong?

Categories

Resources