Majority Element Algorithm Time complexity - java

need help to determine the time complexity for my solution to Majority Element
Problem Description
Task.
The goal of this code problem is to check whether an input sequence contains a majority element.
Input Format.
The first line contains an integer 𝑛, the next one contains a sequence of 𝑛 non-negative
integers 𝑎0, 𝑎1, . . . , 𝑎𝑛−1.
Constraints.
1 ≤ 𝑛 ≤ 105
; 0 ≤ 𝑎𝑖 ≤ 109
for all 0 ≤ 𝑖 < 𝑛.
Output Format.
Output 1 if the sequence contains an element that appears strictly more than 𝑛/2 times,
and 0 otherwise.
Sample 1.
Input:
5
2 3 9 2 2
Output:
1
public class MajorityElement {
private static int getMajorityElement( int count, int right) {
//write your code here
if ((float) count > (float) right / 2) {
return 1;
}
return -1;
}
public static void main(String[] args) {
FastScanner scanner = new FastScanner(System.in);
HashMap<String, Integer> map = new HashMap<>();
int n = scanner.nextInt();
int c = 0;
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = scanner.nextInt();
if (map.get(String.valueOf(a[i])) == null) {
map.put(String.valueOf(a[i]), 1);
} else {
int count;
count = map.get(String.valueOf(a[i])) + 1;
map.put(String.valueOf(a[i]), count);
if (c < count) {
c=count;
}
}
}
if (getMajorityElement( c, a.length) != -1) {
System.out.println(1);
} else {
System.out.println(0);
}
}
static class FastScanner {
BufferedReader br;
StringTokenizer st;
FastScanner(InputStream stream) {
try {
br = new BufferedReader(new InputStreamReader(stream));
} catch (Exception e) {
e.printStackTrace();
}
}
String next() {
while (st == null || !st.hasMoreTokens()) {
try {
st = new StringTokenizer(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return st.nextToken();
}
int nextInt() {
return Integer.parseInt(next());
}
}
}

The complexity of the function getMajorityElement is O(1), because you are doing a simple logic inside the function, but the complexity of the entire code is O(n) because you have a loop that runs n times.

Related

Why does this binary search code give wrong output on Eclipse IDE?

Why does this binary search code give wrong output on Eclipse IDE but gets accepted when submitted to Coursera? This is a sample input for which it shows the wrong output.
Sample Input:
5 3 2 4 1 5
3 1 2 7
Output:
-1 -1 -1
Clearly, the element '1' is present is the input array. But the output for that is -1 instead of 3.
import java.io.*;
import java.util.*;
public class BinarySearch {
static int binarySearch(int[] a,int l,int r,int x) {
//write your code here
if(l<=r){
int mid =l + (r - l)/2;
if(x==a[mid])
return mid;
else if(x<a[mid]){
return binarySearch(a,l,mid-1,x);
}
else
return binarySearch(a,mid+1,r,x);
}
return -1;
}
public static void main(String[] args) {
FastScanner scanner = new FastScanner(System.in);
int n = scanner.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = scanner.nextInt();
}
int m = scanner.nextInt();
int[] b = new int[m];
for (int i = 0; i < m; i++) {
b[i] = scanner.nextInt();
}
for (int i = 0; i < m; i++) {
//replace with the call to binarySearch when implemented
System.out.print(binarySearch(a,0,n-1,b[i]) + " ");
}
}
static class FastScanner {
BufferedReader br;
StringTokenizer st;
FastScanner(InputStream stream) {
try {
br = new BufferedReader(new InputStreamReader(stream));
} catch (Exception e) {
e.printStackTrace();
}
}
String next() {
while (st == null || !st.hasMoreTokens()) {
try {
st = new StringTokenizer(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return st.nextToken();
}
int nextInt() {
return Integer.parseInt(next());
}
}
}
Actually, the problem is with your input data and not the code itself. If you search information about binary search you can find: "binary search is a search algorithm that finds the position of a target value within a sorted array". Your input isn't sorted.
You would have to sort the array before running the search which would be a bad idea - searching with other algorithm would take less time than sorting.
If you try to input sorted data, eg.:
5 1 2 3 4 5
3 1 2 7
The result will be 0 1 -1 - just as expected.

How to find a number with no digit occurring more than once (J3 CCC 2013 from 1987 to 2013)

I'm a grade 11 student and have been given the task to complete this question for homework:
Problem J3/S1: From 1987 to 2013
You might be surprised to know that 2013 is the first year since 1987
with distinct digits.
The years 2014, 2015, 2016, 2017, 2018, 2019
each have distinct digits.
2012 does not have distinct digits,
since the digit 2 is repeated.
Given a year, what is the next year with distinct digits?
Input
The input consists of one integer Y (0 ≤ Y ≤ 10000),
representing the starting year.
Output
The output will be the single integer D,
which is the next year after Y with distinct digits.
Sample Input 1
1987
Sample Output 1
2013
Sample Input 2
999
Sample Output 2
1023
I usually answer these types of questions rather quickly but I am stumped when it comes to this one. I have spent several hours and cannot figure it out. I found out How to identify if a number is distinct or not, but I can't figure out how to add on years and check again, I keep getting errors. I would really appreciate someone's help.
Please keep in mind that I am in grade 11 and this is my first year of working with Java, so please do not use advanced coding, and methods because I won't understand. If you can, please answer it in a class and not the main method.
here is what I tried:
import java.util.*;
import java.io.*;
public class Leavemealone
{
public static void main(String[] args) throws IOException
{
BufferedReader objReader = new BufferedReader(new InputStreamReader(System.in));
int ctr = 0;
String inputStr = "";
int input = 0;
int inputCheck = 0;
System.out.println("Enter somthin: ");
input = Integer.parseInt (objReader.readLine ());
while(ctr == 0)
{
inputStr += input;
Scanner sc = new Scanner(inputStr);
int n = sc.nextInt(); // get year
String s = String.valueOf(n);
int[] num = new int[4];
for (int i = 0; i < s.length(); i++)
{
int x = Integer.parseInt(s.substring(i, i + 1)); // integer at this part in the string
num[i] += x;
}
String apple = (num[0] + "" + num[1] + "" + num[2] + "" + num[3]);
if (num[0] != num[1] &&
num[1] != num[2] &&
num[2] != num[3] &&
num[0] != num[2] &&
num[0] != num[3] &&
num[1] != num[3])
{
ctr++;
//distinct
}
else
{
input++;
//not distinct
}
}
}
}
Thanks in advance!
this is the other code I found online, I just don't know how to put it in a class
import java.util.Scanner;
import java.io.*;
public class Thegoodone
{
public static void main(String[] args) throws IOException
{
BufferedReader objReader = new BufferedReader(new InputStreamReader (System.in));
int ctr = 0;
String input = "";
int inputCheck = 0;
while (ctr == 0)
{
System.out.println("Enter somthin: ");
inputCheck = Integer.parseInt (objReader.readLine ());
if (inputCheck > 0 && inputCheck < 10000)
{
input += inputCheck;
ctr += 1;
}
else
{
System.out.println("invalid input ");
}
}
Scanner sc = new Scanner(input);
int n = sc.nextInt(); // get year
n++; // start from the next year
while (!hasDistinctDidgets(n)) //if there is repeating digits
{
n++;// next year
}
System.out.println(n);// prints year
}
public static boolean hasDistinctDidgets(int n)
{
//System.out.println("a" + n);
String s = String.valueOf(n); // converts the year from int to String
int[] numbers = new int[10]; // index position represents number, element value represents occurrence of that number
for (int i = 0; i < s.length(); i++)
{
int x = Integer.parseInt(s.substring(i, i + 1)); // integer at this part in the string
numbers[x]++; //increase occurrence of this integer in the array
}
//check if any digit occurred more than once in the array
for (int i = 0; i < numbers.length; i ++)
{
if (numbers[i] > 1) //digit occurred more than once
{
return false; //not distinct
}
}
return true; // hasn't returned false yet, so the integer has distinct digits
}
}
so this is how I tried to put it in a class:
import java.util.Scanner;
import java.io.*;
public class Danny3
{
public static void main(String[] args) throws IOException
{
BufferedReader objReader = new BufferedReader(new InputStreamReader (System.in));
int ctr = 0;
String input = "";
int inputCheck = 0;
while (ctr == 0)
{
System.out.println("Enter somthin: ");
inputCheck = Integer.parseInt (objReader.readLine ());
if (inputCheck > 0 && inputCheck < 10000)
{
input += inputCheck;
ctr += 1;
}
else
{
System.out.println("invalid input ");
}
}
Scanner sc = new Scanner(input);
// System.out.println(output);
int n = sc.nextInt(); // get year
n++; // start from the next year
DistinctCheck processing = new DistinctCheck(n);
int output = processing.getSum();
System.out.println(output);
}
}
class DistinctCheck
{
//private int year = 0;
private boolean hasDistinctDidgets;
private int b = 0;
DistinctCheck(int temp)
{
hasDistinctDidgets(temp);
}
private void yearAdd(int b)
{
while(!hasDistinctDidgets(b)) //if there is repeating digits
{
b++;// next year
}
}
private boolean hasDistinctDidgets(int year)
{
String s = String.valueOf(year); // converts the year from int to String
int[] numbers = new int[10]; // index position represents number, element value represents occurrence of that number
for (int i = 0; i < s.length(); i++)
{
int x = Integer.parseInt(s.substring(i, i + 1)); // integer at this part in the string
numbers[x]++; //increase occurrence of this integer in the array
}
//check if any digit occurred more than once in the array
for (int i = 0; i < numbers.length; i ++)
{
if (numbers[i] > 1) //digit occurred more than once
{
return false; //not distinct
}
}
return true; // hasn't returned false yet, so the integer has distinct digits
}
int getSum()
{
return b;// prints year
}
}
I would start with a method to determine if a given int consists of distinct digits. You could use a Set<Character> and add each character from the String to the Set. You will get false on a duplicate. Like,
static boolean distinctDigits(int i) {
String s = String.valueOf(i);
Set<Character> set = new HashSet<>();
for (char c : s.toCharArray()) {
if (!set.add(c)) {
return false;
}
}
return true;
}
Then your main just needs to invoke that. Like,
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int v = s.nextInt();
while (v < 10000) {
v++;
if (distinctDigits(v)) {
break;
}
}
System.out.println(v);
}
i figured it out:
import java.util.*;
public class Apple
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
int num = input.nextInt();
Distinct findDistinct = new Distinct(num); // objecct
String output = findDistinct.getDistinctYear();
System.out.println(output);
}
} // end of main
class Distinct
{
private int ctr = 0;
private String yearStr = "";
private String distinctYear = "";
private int year = 0;
Distinct(int n)
{
year = n;
makeDistinct();
}
private void makeDistinct()
{
while(ctr == 0)
{
year += 1; // year will keep increasing until it is distinct
yearStr = Integer.toString(year);
if(isDistinct(yearStr) == true) // if the number is distinct
{
distinctYear = yearStr;
ctr++;
}
}
}
private boolean isDistinct(String yearStr)
{
String eachNum[] = yearStr.split(""); // breaks up each number (char) of yearStr
for(int i = 0; i < eachNum.length; i++)
{
for(int j = 0; j < i; j++)
{
if (eachNum[i].equals(eachNum[j])) // not distinct
{
return false;
}
}
}
return true; // is distinct
}
String getDistinctYear()
{
return distinctYear;
}
}

creating a list of palindrome numbers

I'm trying to create a List of palindrome numbers that made from the product of two 3-digit numbers but it is returning []. What am I doing wrong?
edit: I couldn't add the isPalindrome function initially cause stackoverflow would complain that "my post mostly code" Is there anything wrong with my isPalindrome function?
public class Solution {
//list of digit numbers of a number
ArrayList<Long> digits = new ArrayList<>();
//list of palindrome numbers
public ArrayList<Long> pal = new ArrayList<>();
// checks if the given number is a palindrome
boolean isPalindrome(long num) {
// creates list of digit numbers of a number
// ex. 12345 -> [5,4,3,2,1]
while(num > 0) {
long lastdigit = num % 10;
digits.add(lastdigit);
num = num / 10;
}
//checks if the number is a palindrome by checking the first and last index
// when the number of digits is even
if(digits.size() % 2 == 0) {
while(digits.size() > 0) {
int last = digits.size() - 1;
if (digits.get(0) == digits.get(last)) {
digits.remove(last);
digits.remove(0);
}
else {
return false;
}
}
return true;
}
// when the number of digits is odd
else while(digits.size() > 1) {
int last = digits.size() - 1;
if (digits.get(0) == digits.get(last)) {
digits.remove(last);
digits.remove(0);
}
else {
return false;
}
}
return true;
}
ArrayList<Long> findPal() {
for (long i = 100; i <= 999; i++) {
for (long j = 100; j <= 999; j++) {
Long product = i * j;
if (isPalindrome(product)) {
pal.add(product);
}
}
}
return pal;
}
public static void main(String[] args) {
Solution sol = new Solution();
System.out.println(sol.isPalindrome((long)121)); //true
System.out.println(sol.isPalindrome((long)12345)); // false
System.out.println(sol.findPal()); //[]
}
}
The problem is most likely in the isPalindrome method that you haven't shown us.
There are a couple of other problems:
The pal field should really be a local variable in the findPal method. (Hint: what happens if you call findPal() twice? Once you have found the bug in isPalindrome, try it ....)
The list of palindromic numbers that you create will most likely contain duplicates. For example, if 104 x 521 is a palindromic number, then 521 x 104 will be as well.
You must have a function in which after passing the number from the loops it should seperate the numbers to a single digit and should return true if the reverse is also true
For eg:
121 - >121%10 - >1
Then 121/10 -> 12
Similarly keep doing this till its modulus is not zero
Then multiply the highest number with (len of digit -1) like
1*100+2*10+1
If it is same then it is palindrome
I know its quite long but its the simplest thing!
Edit:
In isPalindrome() function
if (digits.get(0) == digits.get(last)) {
digits.remove(last);
digits.remove(0);
}
else {
return false;
}
Here in Else block you need to empty the digits list. that is the main problem that you are not emptying it.
I just use your code and just created my isPalindrome function and everything is working fine.
Have a look at this code.
public class Solution {
ArrayList<Long> digits = new ArrayList<>();
ArrayList<Long> pal = new ArrayList<>();
ArrayList<Long> findPal() {
for (long i = 100; i <= 999; i++) {
for (long j = 100; j <= 999; j++) {
Long product = i * j;
if (isPalindrome(product)) {
pal.add(product);
}
}
}
return pal;
}
public static void main(String[] args) {
Solution sol = new Solution();
System.out.println(sol.isPalindrome((long) 121)); // true
System.out.println(sol.isPalindrome((long) 12345)); // false
System.out.println(sol.findPal()); // []
}
private boolean isPalindrome(Long longValue) {
Long temp = longValue;
String tempLong = "";
while (temp != 0) {
tempLong = tempLong + temp % 10 + "";
temp = temp / 10;
}
return Long.parseLong(tempLong) == longValue;
}
}

Reduce the value of a letter, e.g. can change 'd' to 'c', but cannot change 'c' to 'd'. In order to form a palindrome

public class Solution {
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int tc = Integer.parseInt(br.readLine());//I get Numberformat Exception here
for(int i=0;i<tc;i++) // Even if my inputs are on separate lines
{
String original = br.readLine();
palindrome(original);
}
}
public static void palindrome(String original)
{
String reverse="";
int length = original.length();
for ( int i = length - 1 ; i >= 0 ; i-- )
reverse = reverse + original.charAt(i);
if (original.equals(reverse))
{
System.out.println(0);
}
else
{
char[] org = original.toCharArray();
int len = org.length;
int mid = len / 2;
if(len % 2 == 0)
{
char[] front = new char[mid];
char[] back = new char[mid];
for(int i=0;i<mid;i++)
{
front[i] = org[i];
}
int j=0;
for(int i=len-1;i>=mid;i--)
{
back[j] = org[i];
j++;
while(j > mid)
{
break;
}
}
change(front,back,mid);
}
else
{
char[] front = new char[mid];
char[] back = new char[mid];
for(int i=0;i<mid;i++)
{
front[i] = org[i];
}
int j=0;
for(int i=len-1;i>mid;i--)
{
back[j] = org[i];
j++;
while(j > mid)
{
break;
}
}
change(front,back,mid);
}
}
}
public static void change(char[] front,char[] back,int len)
{
int count =0;
for(int i =0;i<len;i++)
{
if(front[i] != back[i] )
{
count += (back[i] - front[i]);
}
}
System.out.println(count)
}
}
What i try to do here is get an input from the number of test cases say 3 in my first line followed by the test-cases themselves.
sample input :
3
abc
abcba
abcd
Now it has to check if the string is a palindrome if its so it ll print 0
else it breaks the string into two halves front and back and finds the minimum number of changes to make it a palidrome.
here i have also checked if its a odd or even length string if odd i have omitted the middle char.
By changes we can only change 'd' to 'b' not 'b' to 'd'
Once a letter has been changed to 'a', it can no longer be changed.
My code works fine for the above input but it doesnt for some other inputs i dont quiet understand why..
for instance if i give a custom test case as
5
assfsdgrgregedhthtjh
efasfhnethiaoesdfgv
ehadfghsdfhmkfpg
wsertete
agdsjgtukgtulhgfd
I get a Number Format Exception.
Your code works fine here, whithout NumberFormatException: http://ideone.com/QJqjmG
This may not solve your problem, but improves your code...
As first user input you are expecting an integer. You are parsing the String returned by br.readLine() and do not take care of the NumberFormatException parseInt(...) may throw.
Just imagine someone hits space or return key as first input.
So I propose to put a try-catch-block around the parseInt(...). Here is an example how this may look like.
Guys thank you for all your suggestion i just found out why my other test cases weren't working
public static void change(char[] front,char[] back,int len)
{
int count =0;
for(int i =0;i<len;i++)
{
if(front[i] != back[i] )
{
count += (back[i] - front[i]);
}
}
System.out.println(count)
}
This part of my code has to be changed to
public static void change(char[] front,char[] back,int len)
{
int count =0;
for(int i =0;i<len;i++)
{
if(front[i] != back[i] )
{
char great = findGreatest(front[i],back[i]);
if(great == back[i])
{
count += (back[i] - front[i]);
}
else
{
count += (front[i] - back[i]);
}
}
}
System.out.println(count);
}
public static char findGreatest(char first,char second)
{
int great = first;
if(first < second)
{
great = second;
}
return (char)great;
}
Because i get negative values coz of subtracting ascii's which are greater than them and as i have already mentioned i can only do 'd' to 'a' not the other way round.
Thank you for your time guys!

interviewstreet.com - String similarity

I'm trying to solve the string similarity question on interviewstreet.com. My code is working for 7/10 cases (and it is exceeding the time limit for the other 3).
Here's my code -
public class Solution {
public static void main(String[] args) {
Scanner user_input = new Scanner(System.in);
String v1 = user_input.next();
int number_cases = Integer.parseInt(v1);
String[] cases = new String[number_cases];
for(int i=0;i<number_cases;i++)
cases[i] = user_input.next();
for(int k=0;k<number_cases;k++){
int similarity = solve(cases[k]);
System.out.println(similarity);
}
}
static int solve(String sample){
int len=sample.length();
int sim=0;
for(int i=0;i<len;i++){
for(int j=i;j<len;j++){
if(sample.charAt(j-i)==sample.charAt(j))
sim++;
else
break;
}
}
return sim;
}
}
Here's the question -
For two strings A and B, we define the similarity of the strings to be the length of the longest prefix common to both strings. For example, the similarity of strings "abc" and "abd" is 2, while the similarity of strings "aaa" and "aaab" is 3.
Calculate the sum of similarities of a string S with each of it's suffixes.
Input:
The first line contains the number of test cases T. Each of the next T lines contains a string each.
Output:
Output T lines containing the answer for the corresponding test case.
Constraints:
1 <= T <= 10
The length of each string is at most 100000 and contains only lower case characters.
Sample Input:
2
ababaa
aa
Sample Output:
11
3
Explanation:
For the first case, the suffixes of the string are "ababaa", "babaa", "abaa", "baa", "aa" and "a". The similarities of each of these strings with the string "ababaa" are 6,0,3,0,1,1 respectively. Thus the answer is 6 + 0 + 3 + 0 + 1 + 1 = 11.
For the second case, the answer is 2 + 1 = 3.
How can I improve the running speed of the code. It becomes harder since the website does not provide a list of test cases it uses.
I used char[] instead of strings. It reduced the running time from 5.3 seconds to 4.7 seconds and for the test cases and it worked. Here's the code -
static int solve(String sample){
int len=sample.length();
char[] letters = sample.toCharArray();
int sim=0;
for(int i=0;i<len;i++){
for(int j=i;j<len;j++){
if(letters[j-i]==letters[j])
sim++;
else
break;
}
}
return sim;
}
used a different algorithm. run a loop for n times where n is equals to length the main string. for each loop generate all the suffix of the string starting for ith string and match it with the second string. when you find unmatched character break the loop add j's value to counter integer c.
import java.io.BufferedReader;
import java.io.InputStreamReader;
class Solution {
public static void main(String args[]) throws Exception {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(in.readLine());
for (int i = 0; i < T; i++) {
String line = in.readLine();
System.out.println(count(line));
}
}
private static int count(String input) {
int c = 0, j;
char[] array = input.toCharArray();
int n = array.length;
for (int i = 0; i < n; i++) {
for (j = 0; j < n - i && i + j < n; j++)
if (array[i + j] != array[j])
break;
c+=j;
}
return c;
}
}
I spent some time to resolve this question, and here is an example of my code (it works for me, and pass thru all the test-cases):
static long stringSimilarity(String a) {
int len=a.length();
char[] letters = a.toCharArray();
char localChar = letters[0];
long sim=0;
int sameCharsRow = 0;
boolean isFirstTime = true;
for(int i=0;i<len;i++){
if (localChar == letters[i]) {
for(int j = i + sameCharsRow;j<len;j++){
if (isFirstTime && letters[j] == localChar) {
sameCharsRow++;
} else {
isFirstTime = false;
}
if(letters[j-i]==letters[j])
sim++;
else
break;
}
if (sameCharsRow > 0) {
sameCharsRow--;
sim += sameCharsRow;
}
isFirstTime = true;
}
}
return sim;
}
The point is that we need to speed up strings with the same content, and then we will have better performance with test cases 10 and 11.
Initialize sim with the length of the sample string and start the outer loop with 1 because we now in advance that the comparison of the sample string with itself will add its own length value to the result.
import java.util.Scanner;
public class StringSimilarity
{
public static void main(String args[])
{
Scanner user_input = new Scanner(System.in);
int count = Integer.parseInt(user_input.next());
char[] nextLine = user_input.next().toCharArray();
try
{
while(nextLine!= null )
{
int length = nextLine.length;
int suffixCount =length;
for(int i=1;i<length;i++)
{
int j =0;
int k=i;
for(;k<length && nextLine[k++] == nextLine[j++]; suffixCount++);
}
System.out.println(suffixCount);
if(--count < 0)
{
System.exit(0);
}
nextLine = user_input.next().toCharArray();
}
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

Categories

Resources