How to reduce memory: - java

I need to create the input graph(graph with backward edges). Ex: 1-st graph has edges from 1 to 2, from 2 to 3; input graph has edges from 3 to 2, from 2 to 1.
The problem is that I'm creating matrix (N^N memory usage). How to use less memory for this task?
import java.util.Scanner;
public class ReverseGraph{
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int n = Integer.parseInt(scan.nextLine()); // number of vertices
//matrix of vertices
int[][] matrix = new int[n][n];
Scanner sc;
//create graph by input method(if A vertex associates with B vert than put "1" on B row, A column)
for(int i = 0; i < n;i++){
String line = scan.nextLine();
sc = new Scanner(line);
while(sc.hasNextInt()){
matrix[sc.nextInt() - 1][i] = 1;
}
}
scan.close();
//Begin write the input graph
System.out.println(n); //write num of vertices
//write
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
if(matrix[i][j] == 1)
System.out.print((j+1) + " ");
}
System.out.println();
}
}
}

Options for reducing the memory footprint.
An adjacency list implemented as an ArrayList<int[]> where the int[] are 2-element arrays each of which represents a link.
As above, except using a custom class with two int fields to represent a link.
As a HashMap<Integer, HashSet<Integer>> or HashMap<Integer, HashSet<Integer>> or HashMap<Integer, TreeSet<Integer>>, where each set or list represents the destinations of the links.
The equivalent to the above using Trove collection types.
All of these1 are O(L) on the number of links rather O(N^2) on the number if nodes.
1 - Apart from the variations that use TreeSet ...

Related

Array rotation TLE (Time Limit Exceeded)

I am really confused why my java code is not working it is giving TLE on Code Monks on Hacker Earth.
Here is the link to the 1
Link to Question
the first question MONK AND ROTATION
import java.util.Scanner;
class TestClass {
static int[] ar=new int[100001];
public static void main(String args[] ){
Scanner in=new Scanner(System.in);
byte t=in.nextByte();
while(t-->0){
int n=in.nextInt();
int k=in.nextInt()%n;
for(int i=0;i<n-k;i++)
ar[i]=in.nextInt();
for(int i=0;i<k;i++)
System.out.print(in.nextInt()+" ");
for(int i=0;i<n-k;i++)
System.out.print(ar[i]+" ");
System.out.println();
}
}
}
I don't know why is it giving TLE I think there is some infinite loop going.
the question at the site is-
Monk and Rotation
Monk loves to perform different operations on arrays, and so being the principal of HackerEarth School, he assigned a task to his new student Mishki. Mishki will be provided with an integer array A of size N and an integer K , where she needs to rotate the array in the right direction by K steps and then print the resultant array. As she is new to the school, please help her to complete the task.
Input:
The first line will consists of one integer T denoting the number of test cases.
For each test case:
The first line consists of two integers N and K, N being the number of elements in the array and K denotes the number of steps of rotation.
The next line consists of N space separated integers , denoting the elements of the array A.
Output:
Print the required array.
Constraints:
1<=T<=20
1<=N<=10^5
0<=K<=10^6
0<=A[i]<=10^6
Sample Input
1
5 2
1 2 3 4 5
Sample Output
4 5 1 2 3
Explanation
Here T is 1, which means one test case.
denoting the number of elements in the array and , denoting the number of steps of rotations.
The initial array is:
In first rotation, 5 will come in the first position and all other elements will move to one position ahead from their current position. Now, the resultant array will be
In second rotation, 4 will come in the first position and all other elements will move to one position ahead from their current position. Now, the resultant array will be
Time Limit: 1.0 sec(s) for each input file
Memory Limit: 256 MB
Source Limit: 1024 KB
I'm not sure about the correctness of your solution, but try to use StreamTokenizer or BufferedReader instead of Scanner. Scanner is too slow and may result in TLE when you need to read a lot of data.
Reduce the number of reads and writes from/to System.in and System.out.
Look at the following solution
Scanner scanner = new Scanner(System.in);
int noOfTestCases = scanner.nextInt();
for (int i = 0; i < noOfTestCases; i++) {
int arraySize = scanner.nextInt();
int noOfRotations = scanner.nextInt();
noOfRotations = noOfRotations % arraySize;
scanner.nextLine();
String inputString = scanner.nextLine();
String[] inputStringArray = inputString.split(" ");
StringBuffer sb = new StringBuffer();
for (int j = 0; j < arraySize; j++) {
sb.append(inputStringArray[(arraySize + j - noOfRotations) % arraySize] + " ");
}
System.out.print(sb);
System.out.println("");
}
import java.util.*;
public class temp {
public static void main (String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
while(t-->0){
int n = sc.nextInt();
int k = sc.nextInt();
int p = 0;
int ar[] = new int[n];
for(int i=0;i<n;i++){
ar[i] = sc.nextInt();
}
k %= n;
for(int i=0;i<n;i++){
p = ar[(i+(n-k))%n];
System.out.print(p+" ");
}
System.out.println();
}
}
}
Though I have not used a big sized array in the starting, this code is working fine for all test cases.
Try this one.
Think from a different perspective. Instead of splitting the string and converting it into an array and applying the iterative logic, we can apply a different logic.
The trick is you just need to find the position of the input string where we have to split only once.
By that I mean,
input=>
6 2       //4 is the length of numbers and 2 is the index of rotation
1 2 3 4 5 6     //array (take input as a string using buffered reader)
Here, we just need to split the array string at the 2nd last space i.e. 4th space. So the output can be achieved by just splitting the string once-
5 6 1 2 3 4
first split- 5 6 + space + second split- 1 2 3 4
This logic worked for me and all the test cases passed.
Also don't forget to cover the corner case scenario when array input string is just one number.
Code Snippet-
int count=0;
for(int k=0; k<arr.length(); k++) {
if(arr.charAt(k)==' ')
count++;
if(count==size-rot) {
System.out.println(arr.substring(k+1,arr.length())
+ " " + arr.substring(0,k));
break;
}
}
Problem is in the System.out.print() call that is inside the for-loop. Thats a fairly heavy call and if called too many times and creates an overhead. This solution works:
//import for Scanner and other utility classes
import java.util.*;
class TestClass {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
String input = s.nextLine();
int noOfTests = Integer.parseInt(input);
for (int t = 0; t < noOfTests; t++) {
input = s.nextLine();
String[] str = input.split(" ");
int sizeOfArray = Integer.parseInt(str[0]);
int noOfRotations = Integer.parseInt(str[1]);
String strIntegerArray = s.nextLine();
String[] array = strIntegerArray.split(" ");
printRightRotatedArray(array, noOfRotations, strIntegerArray.length());
}
}
static void printRightRotatedArray(String[] array, int noOfRotations, int lengthOfStr) {
int len = array.length;
int noOfAcutalRotations = noOfRotations % len;
int startingIndex = len - noOfAcutalRotations;
StringBuilder sb = new StringBuilder(lengthOfStr+1);
for (int i = 0; i < len; i++) {
sb.append(array[(startingIndex + i) % len]);
sb.append(" ");
}
System.out.println(sb);
}
}
putting all into string buffer and print at the end worked for me.
class TestClass {
public static void main(String args[] ) throws Exception {
//BufferedReader
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int t = Integer.parseInt(br.readLine());
StringBuilder sb = new StringBuilder();// output
for(int i=0;i<t;i++){
String [] nk=br.readLine().split(" ");
int n= Integer.parseInt(nk[0]);
int k=Integer.parseInt(nk[1]);
String [] a=br.readLine().split(" ");
int split=n-(k%n);
for (int j = split; j < a.length; j++) {
sb.append(a[j]);
sb.append(' ');
}
for (int j = 0 ; j < split; j++) {
sb.append(a[j]);
sb.append(' ');
}
sb.append("\n");
}
System.out.println(sb);
}
}

how to display the closest pair product in array

import java.util.Scanner;
class my
{
public static void main()
{
Scanner sc = new Scanner(System.in);
int t;
int a[] = new int[5];
int l = a.length;
int prod[] = new int[100];
int index[] = new int[100];
int n;
System.out.println("enter a elements into array ");
for(int i = 0;i<5;i++)
{
a[i] = sc.nextInt();
}
for(int i = 0 ;i<4;i++)
{
for(int j = 0;j<(4-i);j++)
{
if(a[j]>a[j+1])
{
t = a[j];
a[j] = a[j+1];
a[j+1] = t;
}
}
}
System.out.println("enter a number");
n = sc.nextInt();
for(int i = 0;i<l-1;i++)
{
prod[i] = a[i]*a[i+1];
index[i] = a[i];
index[i+1]=a[i+1];
}
for(int i = 0;i<l;i++)
{
if(prod[i]!=0)
System.out.println(prod[i]);
}
for(int i = 0;i<l-1;i++)
{
if(n>prod[i]&&n<=prod[i+1])
System.out.println(index[i+1]+"\t"+index[i+2]);
}
}
}
if want to display the closest pair product in array, which nearest to the entered number. but when i entered array element 1, 2 ,3, 5, 4
and after enter the array i am entering number 8 it is display 3, 4 pair from array instead of 5,2. answer would be 5,2 because the product of 5 * 2 is 10 which is closest to entered number is 8.
The problem with the code is that it is just calculating the product of two consecutive elements and than your are simply comparing that with the product of other elements, which is not a correct way.
Since you sort the array a better way to do it is, by using the logic of binary search. And the logic that the product of pair closest to x will have the least difference.
The algorithm which you can use is as followed:
1. Make a variable difference and initialize to Integer.MAX_VALUE;
2. Now traverse the array from both the direction, i.e set index of left = 0, and right = arr.length -1.
3. Loop while left < right.
(a) If abs((arr[left] * arr[right]) - x) < difference
then update difference and result
(b) if((arr[left] * arr[right]) < x) then
left++
(c) Else right--
Time Complexity : O(nlog(n))
I don't understand why you have so many loops and so many variables in your solution. You also don't need to sort the array a.
In pseudo code:
var a[]
var n
var closest = MAX_INTEGER
var closest_i
var closest_j
for i in range [0, a.length)
for j in range [i + 1, a.length)
var distance = abs(a[i] * a[j] - n)
if distance < closest
closest = distance
closest_i = i
closest_j = j
Note that this has O(n) time complexity.

Scalar Multiplication

EDIT
The question is this: Scalar multiplication is defined as B = A * s, where B and A are equally sized matrices (2D array of numbers, in this example let's use integers) and s is a scalar value. Each element of A is multiplied to s, which is then stored in the corresponding element in matrix B.
Write a program that accepts a 4x4 matrix and a scalar value, and perform scalar multiplication, storing the result in a separate 4x4 matrix.
import java.util.*;
public class arrayExercises {
public static void main (String [] args){
//Scalar Value
Scanner sc = new Scanner (System.in);
int scalar = 0;
//Array for A
int matrix [][];
matrix = new int [4][4];
System.out.println("Enter the numbers in the 4x4 matrix");
for (int i=0; i < matrix.length; i++)
{
for (int j =0; j<matrix[i].length; j++)
matrix[i][j] = sc.nextInt();
}
System.out.println("Enter scaler value:");
scalar = sc.nextInt();
sc.close();
}
}
not giving a direct solution. giving you a hint instead.
so far from your code, you have created a matrix and withing 2 for loop you have set the values of the matrix from user input.
now to get a scalar multiplication you need to do a similar operation. create another matrix of the same size as the previous matrix. and in a similar way within 2 loop multiply each and every element of the old matrix with the scalar value and set it to the coresponding index of the new matrix.
System.out.println("Enter scaler value:");
scalar = sc.nextInt();
int scalarMatrix [][];
scalarMatrix = new int [4][4];
for (int i=0; i < scalarMatrix.length; i++)
{
for (int j =0; j<scalarMatrix[i].length; j++)
scalarMatrix[i][j] = (int)(matrix[i][j]*scalar);
}
Something along these lines should work. What you are doing is getting each result from the initial matrix and essentially copying them into the new matrix but multiplying it by the variable "scalar" as you do so.

Finding out the frequency of unique numbers

I am trying to solve a problem in Java as part of my assignment. The problem is as below:
The user enters ten numbers one by one upon prompting by the screen. The screen then assigns all the distinct value to an array and a similar array to hold the frequency of how many times those numbers have appeared.
I have done the below work, but seems I am stuck somewhere in assigning the frequencies and distinct values to the arrays:
import java.util.*;
public class JavaApplication10
{
public static void main(String[] args)
{
int [] numbers = new int [10];
int [] count = new int[10];
int [] distinct = new int[10];
for (int k=0;k<10;k++)
{
count[k]=0;
distinct[k]=0;
}
java.util.Scanner input = new java.util.Scanner(System.in);
System.out.print("Enter number 0: ");
numbers[0]=input.nextInt();
count[0]=1;
distinct[0]=numbers[0];
int j=0;
for (int i = 1;i<10;i++)
{
System.out.print("Enter number "+i+": ");
numbers[i]=input.nextInt();
while(j<i)
{
if (distinct[j]==numbers[i])
count[j]=count[j]+1;
else
distinct[j+1]=numbers[i];
j++;
}
}
for (int k=0;k<10;k++)
{
System.out.println(distinct[k]+ " "+count[k]);
}
}
}
I know that it is not fair to ask someone to help me solve the problem. But any kind of hint will be helpful.
Thank you
are the numbers limited to 0-9? If so, I would simple do the assignment.
(please note you will assign the input to a variable called "input"):
numbers[0]=input;
count[input]++;
Also you can start your for loop in "0" to avoid the assignment prior to the for loop.
Just a hint.
Hope this helps!
the ideal data structure would be a HashMap
Steps:
1) initialize an array to store the numbers and for each input
2) check if a hashmap entry with key as the entered number already exists
3) if exists simply increase its count
4) else create new entry with key as the number and count as 1
so at the end your frequencies would be calculated
if you are forced to use 2 arrays
1) initialize two arrays
2) for each input loop the number array and check whether that number is already in the array
3) if so take the array index and increment the value of the frequency array with the same index
4) if not freq[index] = 1
A proper way of doing that would be:
public Map<Integer, Integer> getFrequencies(Iterable<Integer> numbers) {
Map<Integer, Integer> frequencies = new HashMap<Integer, Integer>();
for(Integer number : numbers) {
if (frequencies.get(number) == null) {
frequencies.put(number, 0);
}
frequencies.put(number, frequencies.get(number) + 1);
}
return frequencies;
}
It returns a map number -> frequency.
Arrays are not a way to go in Java, they should be avoided whenever possible. See Effective Java, Item 25: Prefer lists to arrays.
I removed the Scanner object to write the code faster, just replace it with your code above and it should work.
int[] numbers = { 1, 2, 2, 2, 3, 3, 3, 1, 1, 2 };
int[] count = new int[10];
int[] distinct = new int[10];
count[0] = 1;
distinct[0] = numbers[0];
int disPos = 1; //Current possition in the distinct array
boolean valueInarray = false;
for (int i = 1; i < 10; i++) {
valueInarray = false;
for (int d = 0; d < i; d++) {
if (numbers[i] == distinct[d]) {
count[d] = count[d] + 1;
valueInarray = true;
break;
}
}
if (!valueInarray) {
distinct[disPos] = numbers[i];
count[disPos] = 1;
disPos++;
}
}
If you ABSOLUTELY HAVE TO use arrays.. here is a way to do it…
import java.util.Scanner;
import java.util.Arrays;
public class JavaApplication10
{
public static void main(String[] args)
{
int [] numbers = new int [10];
int [] count = new int[10];
int [] distinct = new int[10];
int [] distinct1 = new int[1];
int distinctCount = 0;
boolean found = false;
Scanner input = new Scanner(System.in);
for (int i=0; i<10; i++) {
found = false;
System.out.print("Enter number " + i);
numbers[i]=input.nextInt(); //Add input to numbers array
for (int j=0; j<=distinctCount; j++)
{
if (distinct1[j] == numbers[i]){ // check to see if the number is already in the distinct array
count[j] = count[j] + 1; // Increase count by 1
found = true;
break;
}
}
if (!found) {
distinct[distinctCount] = numbers[i];
count[distinctCount] = 1;
distinctCount++;
distinct1 = Arrays.copyOf(distinct, distinctCount+1);
}
}
for (int j=0; j<distinctCount; j++)
System.out.println("The number " + distinct1[j] + " occurs " + count[j] + " times" );
}
}
I think this is what you need, correct me if I'm wrong...
import java.util.HashMap;
import java.util.Scanner;
public class JavaApplication10 {
public static void main(String[] args) {
// Initializing variables
int[] numbers = new int[10];
HashMap<Integer, Integer> table = new HashMap<Integer, Integer>();
Scanner input = new Scanner(System.in);
// Getting the 10 inputs
for(int x=0; x<10; x++) {
// Asking for input
System.out.println("Enter number "+x+":");
numbers[x]=input.nextInt();
// If the table contains the number, add 1
// Otherwise: set value to 1
if(table.containsKey(numbers[x]))
table.put(numbers[x], table.get(numbers[x])+1);
else
table.put(numbers[x],1);
}
// Closing the reader
input.close();
// Get the highest and smallest number
int highest=0;
int smallest=0;
for(int i:table.keySet()) {
if(i>highest)
highest=i;
if(i<smallest)
smallest=i;
}
// For every value between the smallest and the highest
for (int x=smallest; x<=highest; x++) {
// Check if the frequency > 0, else continue
if(table.get(x)==null)
continue;
// Output
System.out.println(x+" is "+table.get(x)+" times in \'frequence\'");
}
}
}
This also handles with negative numbers, unlike the other's codes. If you don't want to use HashMaps let me know so I can create something with arrays.
Let me know if it (doesn't) works!
Happy coding (and good luck with your assignment) ;) -Charlie

Creating a distance map for all stations on a train line

I'm revising for a introduction to programming exam and I have a question which from a previous exam paper I am slightly stuck on.
The question:
Write a method that takes a double array as an argument with values representing the positions of train stations along a track. The method should return a two-dimensional array with the distances between each pair of stations in the argument. The array of distances should have only one entry for each pair of stations (i.e. do not use a rectangular array).
I have a solution to the question but I just can't get the last bit where there should only be one entry for each pair. I have thought about creating a look up table will all the entries to see if the distance for the two stations but then the array would have lots of empty cells for the later stations because the distance would have already been calculated.
Here is my current solution
//Set of locations on the train line
private static double[] stations = {0.0, 2.0, 3.0, 5.0};
//Method to take the array of doubles and create distance map
public static double[][] getDistances(double[] st){
double[][] distanceMap = new double[st.length][st.length-1];
int x;
for(int i=0; i<st.length; i++){
x=0;
for(int j=0; j<st.length; j++){
if(j != i){
distanceMap[i][x] = Math.abs(st[i]-st[j]);
x++;
}
}
}
return distanceMap;
}
//Main method to get the distance map then loop over results
public static void main(String[] args){
double[][] arrayMatrix = getDistances(stations);
for(int i=0; i<arrayMatrix.length; i++){
for(int j=0; j<arrayMatrix[0].length; j++){
System.out.print(arrayMatrix[i][j]+" ");
}
System.out.println("");
}
}
If anyone could point me in the right direction it would be really appreciated.
Thanks in advance.
//EDIT
After some great advice from #izomorphius I have managed to solve the question. Thanks.
Here is the complete solution
//Set of locations on the train line
private static double[] stations = {0.0, 2.0, 3.0, 5.0};
//Method to take the array of doubles and create distance map
public static double[][] getDistances(double[] st){
double[][] distanceMap = new double[st.length-1][];
int size = st.length-1;
for(int i=0; i<distanceMap.length; i++){
distanceMap[i] = new double[size];
size--;
}
ArrayList<String> lut = new ArrayList<String>();
int x;
for(int i=0; i<distanceMap.length; i++){
x=0;
for(int j=0; j<st.length; j++){
if(j != i && !lut.contains(i+"/"+j)){
distanceMap[i][x] = Math.abs(st[i]-st[j]);
lut.add(i+"/"+j);
lut.add(j+"/"+i);
x++;
}
}
}
return distanceMap;
}
//Main method to get the distance map then loop over results
public static void main(String[] args){
double[][] arrayMatrix = getDistances(stations);
for(int i=0; i<arrayMatrix.length; i++){
for(int j=0; j<arrayMatrix[i].length; j++){
System.out.print(arrayMatrix[i][j]+" ");
}
System.out.println("");
}
}
What the statement says is "i.e. don't use rectangular array". The idea is to store only one value for each pair. For instance if you have the pair (a,b) and a < b store the distance between a and b in the array of a but not in the one of b. Thus the array for the first station will be of size n - 1(distances to all the other stations), for the second station it will be of size n - 2(all other stations except the first one) and so on. Therefor your array will be triangular not rectangular. I hope this tip is enough as after all the idea is not to have me solve your problem.

Categories

Resources