This was my online interview question, and I already submitted the answer. However, the compilation was terminated due to time so I just submitted. Could I get feedback from you? Thanks in advance.
Problem:
Given N numbers , [N<=10^5] we need to count the total pairs of numbers that have a difference of K
Input Format:
1st line contains N & K (integers).
2nd line contains N numbers of the set. All the N numbers are assured to be distinct.
Output Format:
One integer saying the no of pairs of numbers that have a diff K.
Sample Input #00:
5 2
1 5 3 4 2
Sample Output #00:
3
My code:
import java.io.*
import java.util.*;
public class DiffNumbers {
public static void main(String[] args) throws Exception {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String line1 = in.readLine();
String line2 = in.readLine();
int n = Integer.parseInt(line1.split(" ")[0]);
int diff = Integer.parseInt(line1.split(" ")[1]);
Hashtable table = new Hashtable();
int[] arr = new int[n];
for(in i=0; i<n; i++) {
arr[i] = Integer.parseInt(line2.split(" ")[i]);
table.put(Integer.parseInt(line2.split(" ")[i]));
}
int count = 0;
for(in i=0; i<n; i++) {
if(table.containsKey(arr[i]+diff) {
count++;
}
}
system.out.println(count);
}
}
Using HashMap/Table needs extra space. If you want to avoid it you can do it this way
1) Sort the array
2) initialize outputCount as 0
3) Let there be two pointers. "first" start with 0 and "Other" pointer start with 1.
4)
while(arr[other]-arr[first] <requiredDifference)
other ++;
if(arr[other]-arr[first] == requiredDifference)
outputCount++;
else // no match for arr[first]
first++;
5)
return outputCount;
explanation :-
When difference is more than requiredDifference you stop moving ahead "other" poiner. So there is no match for arr[first]. So move ahead first counter. Now do the same logic for new arr[first]. This time you will continue checking from current position of "other" as array is sorted; lower number will not have required match.
public static void main(String[] args) throws Exception{
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String line1 = in.readLine();
String line2 = in.readLine();
int diff = Integer.parseInt(line1.split(" ")[1]);
Map<Integer, Object> nMap = new HashMap<Integer, Object>();
Map<Integer, Boolean> uMap = new HashMap<Integer, Boolean>();
Map<Integer, Boolean> lMap = new HashMap<Integer, Boolean>();
String[] numbers = line2.split(" ");
//init maps
for(String number : numbers){
Integer intValue = Integer.valueOf(number);
nMap.put(intValue, new Object()); //original set, N
uMap.put(intValue + diff, false); //upper-bound map
lMap.put(intValue - diff, false); //lower-bound map
}
int count = 0;
for(Integer nKey : nMap.keySet()){
//Do if the lower-bound of n exists in N and if n hasn't used as an upper-bound?
if(nMap.get(nKey - diff) != null && !uMap.get(nKey)){
count++;
//Mark the lower-bound as used.
lMap.put(nKey - diff, true);
}
//Do if the upper-bound of n exists in N and if n hasn't used as an lower-bound?
if(nMap.get(nKey + diff) != null && !lMap.get(nKey)){
count++;
//Mark the upper-bound as used.
uMap.put(nKey + diff, true);
}
}
System.out.println(count);
}
There's not much reason to store the integers in both an array and a hashtable. We can modify your code to do the all of the work in a single for loop.
for(int i=0; i<n; i++) {
int j = Integer.parseInt(line2.split(" ")[i]) //probably not how I would go about this
table.put(j);
if(table.containsKey(j+diff)) {
count++;
}
if(table.containsKey(j-diff)) {
count++;
}
}
Related
I have a scanner which reads in strings as coordinate inputs. I have to convert these strings into integers and store them in an Arraylist of coordinates but the last values I input are not being stored in the arraylist.
I have tried using the startEndLineScan.nextLine(); outside the for-loop but still no change I have also tried using a while loop instead of a for loop when storing and parsing the strings but I get the same results.
ArrayList<Integer> convertedCoords = new ArrayList<Integer>();
String samplePointsCoords[];
Scanner startEndLineScan = new Scanner(System.in);
int count = 1;
while (startEndLineScan.hasNextLine()) {
startEndPointsInputs = startEndLineScan.nextLine();
samplePointsCoords = startEndPointsInputs.split(",");
if (count < 2) {
for (int i = 0; i < samplePointsCoords.length; ++i) {
convertedCoords.add(Integer.parseInt(samplePointsCoords[i]));
}
count++;
} else {
break;
}
}
System.out.print("Points: " + convertedCoords)
Input:
1,2
3,4
Expected results:
Points: [1,2,3,4]
Actual Results
Points: [1,2]
ArrayList<Integer> convertedCoords = new ArrayList<Integer>();
String samplePointsCoords[];
Scanner startEndLineScan = new Scanner(System.in);
int count;
while (startEndLineScan.hasNextLine()) {
count = 1;
startEndPointsInputs = startEndLineScan.nextLine();
samplePointsCoords = startEndPointsInputs.split(",");
if (count < 2) {
for (int i = 0; i < samplePointsCoords.length; ++i) {
convertedCoords.add(Integer.parseInt(samplePointsCoords[i]));
}
count++;
} else {
break;
}
}
System.out.print("Points: " + convertedCoords)
Notice int count; is declared and reinitialized at the start of every loop
This will fix your code but you should really try to understand what you are writing! cheers.
This program receives 100 inputs and then outputs the lowest value. I need help checking all duplicated values inputted.
Example with 5 inputs:
5,1,1,5,4
The smallest value: 1
The amount of duplicated values: 4
import java.awt.*;
import hsa.Console;
public class ArrayNumbers
{
static Console c;
public static void main (String[] args)
{
c = new Console ();
int number[] = new int [100], i = 1, output = 0;
c.print ("Enter number #1:");
number [0] = c.readInt ();
output = number [0];
for (int count = 0 ; count < 99 ; count++)
{
c.print ("Enter number #" + (count + 2)+ ":");
number [i] = c.readInt ();
if (number [i] < output)
{
output = number [i];
}
i++;
}
c.print(output);
} // main method
} // ArrayNumbers class
It can be done by using map. Please find below code for the same:
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class MinAndDuplicates {
public static void main(String[] args) {
int number, totalDupCount=0;
Scanner stdin = new Scanner(System.in);
Map<Integer, Integer> map = new HashMap<Integer,Integer>();
//Prepare map with duplicate count for each number
for (int i = 0; i < 5; i++) {
number=stdin.nextInt();
if(map.containsKey(number)){
map.put(number, ((Integer)map.get(number)+1));
}else{
map.put(number, 1);
}
}
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
int numberCount= entry.getValue();
if (numberCount> 1) {
totalDupCount+= numberCount;
}
}
System.out.println(totalDupCount);
}
}
Hope this helps!
Below is the logic to perform your duplicate count in O(n) time and O(1) extra space.
try this
// Function to find counts of all elements present in
// arr[0..n-1]. The array elements must be range from
// 1 to n
// Traverse all array elements
int[] arr = {5,1,1,5,4};
int i = 0,n=arr.length;
int totalDupCount = 0;
while (i < n) {
// If this element is already processed,
// then nothing to do
if (arr[i] <= 0) {
i++;
continue;
}
// Find index corresponding to this element
int elementIndex = arr[i] - 1;
// If the elementIndex has an element that is not
// processed yet, then first store that element
// to arr[i] so that we don't loose anything.
if (arr[elementIndex] > 0) {
arr[i] = arr[elementIndex];
// After storing arr[elementIndex], change it
// to store initial count of 'arr[i]'
arr[elementIndex] = -1;
} else {
// If this is NOT first occurrence of arr[i],
// then increment its count.
arr[elementIndex]--;
// And initialize arr[i] as 0 means the element
// 'i+1' is not seen so far
arr[i] = 0;
i++;
}
}
System.out.println("Below are counts of all elements");
for (int j = 0; j < n; j++){
if(Math.abs(arr[j]) >= 2){
System.out.println(j + 1 + "->" + Math.abs(arr[j]));
totalDupCount +=Math.abs(arr[j]);
}
}
System.out.println("Total Duplicate Count in Array is : "+totalDupCount);
}
Output
Below are counts of all elements
1->2
5->2
Total Duplicate Count in Array is : 4
(This post is slightly uglier than my first approach, but it solves the poster's question the way they'd like it to. I have decided to put it as a separate answer.)
If you want to count the number of duplicated numbers multiple times
depending on how often they show up, you can do it with a
HashMap.
The Approach
Create a HashMap to count how often each number appears.
When reading input, increment the occurrences of that number.
To find the number of "duplicates", iterate through the HashMap and sum all of the occurrences which happen more than once.
Example
import java.util.Scanner;
import java.util.Map;
import java.util.HashMap;
public class DuplicateCounter {
static int[] numbers = new int[100];
static HashMap<Integer, Integer> occurrences = new HashMap<>();
public static void main(String[] args) {
readInput();
int duplicates = countDuplicates();
System.out.printf("%d numbers appeared multiple times.\n", duplicates);
}
public static void readInput() {
Scanner stdin = new Scanner(System.in);
for (int i = 0; i < numbers.length; i++) {
int number = stdin.nextInt();
numbers[i] = number;
incrementCount(number);
}
stdin.close();
}
public static int countDuplicates() {
int duplicates = 0;
for (Map.Entry<Integer, Integer> entry : occurrences.entrySet()) {
int numOfOccurrences = entry.getValue();
if (numOfOccurrences > 1) {
duplicates += numOfOccurrences;
}
}
return duplicates;
}
public static void incrementCount(int number) {
if (occurrences.get(number) != null) {
int previous = occurrences.get(number);
occurrences.put(number, previous + 1);
} else {
occurrences.put(number, 1);
}
}
}
I am currently solving this problem on Hackerrank, and below is the code that I have written so far.
When I ran it, there are a couple of errors: the output is totally wrong even though the input and the process are correct, and when the input is 1, it does not add it into my hashmap. I believe that both errors exist because of using HashMap. For example, if the input is
3(testcases) ==> 12, 5, 7. It will print out Prime, Prime, Not prime instead of the correct output like Not prime, Prime, Prime.
For more information, I commented out the lines,saying "output purposes". You can see, it added to the hashmap in correct order, but when it prints, it messed up.
So, I am just curious if someone can please explain why printing is wrong, and fix for the part when the input is 1.
import java.io.*;
import java.util.*;
public class Solution1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] myarray = new int[n]; // read number of testcases
for(int i=0;i<n;i++){ // add input to my int array
myarray[i]=sc.nextInt();
}
HashMap<Integer, String> newmap = new HashMap <>(); // create empty hashmap
int temp;
int value;
for(int i=0;i<n;i++){ // loop based on num of testcases
temp =myarray[i];
boolean isprime = true;
if(temp ==1){ // hardcode for input 1
isprime = false;
continue;
}
for(int j=2;j<=temp/2;j++){ // checking whether the input is prime or not
value = temp%j;
if(value==0){
isprime = false;
continue;
}
}
if(isprime==true){
//System.out.println("temp(Prime): "+temp); //output purpose
newmap.put(temp,"Prime");
}
else{
//System.out.println("temp(Not prime): "+temp); //output purpose
newmap.put(temp,"Not prime");
}
}
Set set = newmap.entrySet();
Iterator iterator = set.iterator();
//printing out values of the each element in hashmap(newmap)
while(iterator.hasNext()) {
Map.Entry mentry = (Map.Entry)iterator.next();
System.out.println(mentry.getValue());
}
}
}
The problem in your code is that your myarray is not sorted and and when you are inserting into newmap , it's not getting inserted in the desired order.
I recommend you to sort the array and used ordered map like LinkedHashMap or linked list.
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] myarray = new int[n]; // read number of testcases
Arrays.sort(myarray);
for (int i = 0; i < n; i++) { // add input to my int array
myarray[i] = sc.nextInt();
}
HashMap<Integer, String> newmap = new LinkedHashMap<Integer, String>(); // create
// empty
// hashmap
int temp;
int value;
for (int i = 0; i < n; i++) { // loop based on num of testcases
temp = myarray[i];
boolean isprime = true;
if (temp == 1) { // hardcode for input 1
isprime = false;
break;
}
for (int j = 2; j <= temp / 2; j++) { // checking whether the input
// is prime or not
value = temp % j;
if (value == 0) {
isprime = false;
break;
}
}
if (isprime == true) {
// System.out.println("temp(Prime): "+temp); //output purpose
newmap.put(temp, "Prime");
} else {
// System.out.println("temp(Not prime): "+temp); //output
// purpose
newmap.put(temp, "Not prime");
}
}
Set set = newmap.entrySet();
Iterator iterator = set.iterator();
// printing out values of the each element in hashmap(newmap)
while (iterator.hasNext()) {
Map.Entry mentry = (Map.Entry) iterator.next();
System.out.println(mentry.getValue());
}
}
}
#Jim Lewis and #Michael Markidis have already provided the right answers for how to fix the bugs in this code.
I think to satisfy the requirements of the coding exercise you're doing, you'll need to output the results in the same order as the input numbers, so you'll want to collect the results into something with an order, rather than the (unordered) HashMap. Here's some slightly cleaned up code that uses an ArrayList instead (though frankly you should be able to just print out the results as you go):
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] inputs = new int[n]; // read number of testcases
for (int i = 0; i < n; i++) { // add input to my int array
inputs[i] = sc.nextInt();
}
List<String> results = new ArrayList<>();
for (int number : inputs) {
boolean isprime = true;
if (number == 1) { // hardcode for input 1
isprime = false;
} else {
for (int j = 2; j <= number / 2; j++) { // checking whether the input is prime or not
if (number % j == 0) {
isprime = false;
continue;
}
}
}
results.add(isprime ? "Prime" : "Not prime");
}
for (String result : results) {
System.out.println(result);
}
}
}
A HashMap doesn't have predictable order. However, you can print out the keys associated with each value like this:
for (Iterator<Integer> iter = newmap.keySet().iterator(); iter.hasNext(); )
{
int key = iter.next();
System.out.println(key + "=" + newmap.get(key));
}
This will output:
5=Prime
7=Prime
12=Not prime
EDIT: As suggested by MeBigFatGuy and smarx, an entrySet() iterator is better while used with an enhanced loop.
Example:
for (Map.Entry mentry : newmap.entrySet())
{
System.out.format("%s = %s\n", mentry.getKey(), mentry.getValue());
}
You are assuming that the Iterator over the entrySet of your Hashmap will return the entries in the same order you added them. A plain old HashMap guarantees nothing of the sort (no pun intended). Try using a LinkedHashMap instead.
While checking for 1 , update in map before continue;
Inside Inner for loop ,
Use break instead of continue
Some tweaks
- If your array doesn't have duplicates then dont waste memory in
hashmaps. Loop on array.
coding exercises has large input to be read , use bufferedreader instead for faster throughput
use generics properly
I would like to ask you a question, I want to count how many times a specified number is in a given numer (long) from the user and print it as an int.
Could you please help me with this code?
Apologize for my english.
Example:
< number specified = 4; number given = 34434544; result = 5. >
Check whether the least-significant digit is equal to the digit you are searching for; then divide by ten and check again; keep going until you reach zero.
int cnt = 0;
while (value != 0) {
if (value % 10 == digit) ++cnt;
value /= 10;
}
Where you are trying to count the occurrences of digit in the big number value.
If you're using Java 8:
long count = String.valueOf(givenNumber).chars()
.filter(c -> c == (specifiedNumber + '0'))
.count();
Make a Scanner to get input from System.in. Then, iterate through the String returned by turning it into a char[]. Then analyse each char and count original characters. Probably use a Map<Character, Integer> for this. For each element in the Map, iterate by one if it is in the Map. Query the Map for your desired character and print the result when finished.
public static void main(String[] args) {
CharacterFinder cf = new CharacterFinder();
Scanner scan = new Scanner(System.in);
String input = scan.nextLine();
Map<Character, Integer> resultsMap = cf.countChar(input);
System.out.println(resultsMap.get('g'));
}
// Note that 'null' means that it does not appear and if it is null, you ought print 0 instead.
// Also note that this method is case sensitive.
private Map<Character, Integer> countChar(String input) {
Map<Character, Integer> resultsMap = new HashMap<Character, Integer>();
for (int i = 0; i < input.length(); i++) {
Character element = input.charAt(i);
if (resultsMap.containsKey(element)) {
Integer cCount = resultsMap.get(element);
resultsMap.put(element, cCount + 1);
} else {
resultsMap.put(element, 1);
}
}
return resultsMap;
}
Well, unless you already know the char you want. In that case, analyse for that exact char.
public static void main(String[] args) {
CharacterFinder cf = new CharacterFinder();
Scanner scan = new Scanner(System.in);
String input = scan.nextLine();
// Call counting method and print
System.out.println(cf.countChar(input, '5'));
}
// Counting method
private int countChar(String input, char c) {
int x = 0;
for (int i = 0; i < input.length(); i++) {
if (input.charAt(i) == c) {
x++;
}
}
return x;
}
so basically i have C:/180301.txt file in which i have 1 1 2 2 3 4 5 numbers\bytes and output(49) is correct i think. my qustion is how to print out all elements which coming repetiteve times, now i have only one its 49
private static ArrayList<Integer> list1 = new ArrayList<>();
private static ArrayList<Integer> list2 = new ArrayList<>();
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
FileInputStream fileReader = new FileInputStream(br.readLine());
while (fileReader .available() > 0)
{
list1.add(fileReader .read());
}
int element = 0;
int count = 0;
for (int i = 0; i < list1.size(); i++)
{
if (same_element(list1.get(i)))
{
for (int j = 0; i < list1.size(); i++)
{
if (list1.get(i).equals(list1.get(j)))
{
count++;
element = list1.get(j);
list2.add(list1.get(i));
}
}
}
}
if (count > 1)
System.out.println(element);
fileReader.close();
}
private static boolean same_element(int list_i) {
for (Integer aList2 : list2) if (list_i == aList2) return false;
return true;
}
}
In same_element you have to switched true and false. 49 is prtinted because you never increase j. So the inner loop is buggy, too. But it should be deleted anyway because same_element now should do that job. The third problem is that you add the recent value only to the list of already seen value if it's already in there. That can't ever happen. So with some slight reworks your code might look like this:
List<Integer> fromFile = new ArrayList<>();
InputStream fileReader = new ByteArrayInputStream("71123456".getBytes("utf-8"), 0, 8);
while (fileReader.available() > 0)
{
fromFile.add(fileReader.read());
}
int element = 0;
int count = 0;
List<Integer> seen = new ArrayList<>();
for (int i = 0; i < fromFile.size(); i++)
{
Integer recent = fromFile.get(i);
if (seen.contains(recent))
{
count++;
element = recent;
}
seen.add(recent);
}
if (count > 1) System.out.println(element);
fileReader.close();
This prints the last duplicate, but still not the byte with most occurences. Today we write it like this:
Map<Byte, Integer> counters = new HashMap<>();
Path path = FileSystems.getDefault().getPath(args[0]);
// build a map with byte value as a key refering to a counter in the value
for (Byte b: Files.readAllBytes(path)) {
Integer old = counters.get(b);
counters.put(b, (old == null ? 1 : old + 1));
}
// create a comparator that orders Map.Entry objects by their value. I.E. the
// occurences of the respective byte. The order is ascending.
Comparator<Entry<Byte, Integer>> byVal = Comparator.comparingInt(e -> e.getValue());
// create a stream of Map.Entry objects. The stream is a new concept of Java8.
// That's somehow like a collection, but more powerful. While the collection
// stores data he stream has a focus on manipulating
counters.entrySet().stream()
// Use the comaparator in reversed form. That means the number of
// occurences is now descending
.sorted(byVal.reversed())
// only use the first Map.Entry. I.E. the one with most occurences
// a similar functionality is by filter.
// .filter(e -> e.getValue() > 1) would use all duplicates
.limit(1)
// print out the results. Of course the argument for println can be
// concatenated from several parts like:
// e.getKey() + "\tcount: " + e.getValue()
.forEach(e -> System.out.println(e.getKey()));
Java 8 helps a lot for problems like this. Tying to write the same with former versions take quite a bit more code.