Parity - Recursion java - java

I have the Parity checker problem: A binary string is a string that contains only '0' and '1'characters. The parity of a binary
string is defined as follows. If the number of times that the character '1' appears in this string
is even, the parity it 0; if it’s odd, the parity is 1. For example, the parity of "101" is 0, the
parity of "10110" is 1, and the parity of "001001101" is 0. Write a function, using the signature
public static int parity(String binaryStr)
//no changes are allowed & only use recursive solution, no loops allowed
I managed to write it iteratively however my recursion is out of outOfboundries:
public static int parity(String binaryStr) {
int counter = 0;
for (int i = 0; i < binaryStr.length () ; i++) {
if (binaryStr.charAt (i) == 49) {
counter++;
}
}
if ( counter % 2 == 0 ) {
return 0;
}
else {
return 1;
}
}
recursive:
private static int index = 0;
private static int ans = 0;
private static int parity(String binaryStr) {
if ( index == binaryStr.length ()-1 ) {
if ( ans % 2 == 0 ) {
return 0;
}
else {
return 1;
}
}
else if ( binaryStr.charAt (index) == '1' ) {
ans++;
return parity (binaryStr.substring (index++));
}
return parity (binaryStr.substring (index++));
}
please help me correct it

The major issue with your code is passing binaryStr.substring (index++) to the recursive call, which passes the original String instead of a substring. Hence you get infinite recursion. You can use ++index.
Instead of using static variables, I suggest the following:
private static int parity(String binaryStr) {
if (binaryStr.length() == 0) {
return 0;
} else {
return ((binaryStr.charAt(0) == '0') ? 0 : 1) ^ parity(binaryStr.substring(1));
}
}
Explanation:
If the two operands of bit-wise XOR (^) are equal, it returns 0. If one operands is 0 and the other is 1, it returns 1.
That's exactly the logic you need:
If the first character is '1' and the rest of the String has parity 1 (i.e. odd number of '1's), the whole String's parity is 0.
If the first character is '1' and the result of the String has parity 0 (i.e. even number of '1's, the wholeString`'s parity is 1.
If the first character is '0', the parity of the whole String is the same as the parity of the rest of the String.

Related

First Unique Character In a String-Leetcode

I have tried out 387.First Unique Character In A string
Given a string s, find the first non-repeating character in it and
return its index. If it does not exist, return -1.
EXAMPLE : 1
Input: s = "leetcode"
Output: 0
EXAMPLE :2
Input: s = "loveleetcode"
Output: 2
I have been trying this problem. I thought we will pick one by one all the characters and check if a repeating character exists break from the loop. And if not then return that index.I have thought over a solution which I believe is not the most efficient way but I want to know the how can I solve this problem with the approach given below:
public int firstUniqChar(String s) {
for(int i=0;i<s.length();i++){
for(int j=i+1;j<s.length();j++){
if(s.charAt(i)==s.charAt(j)){
break;
}
}
}
return -1;
}
I'm confused how to return the index.I'm unable to find the logic after:
for(int j=i+1;j<s.length();j++){
if(s.charAt(i)==s.charAt(j)){
break;
}
}
If anyone can help me find out the logic here.
Try this.
public static int firstUniqChar(String s) {
L: for (int i = 0, length = s.length(); i < length; i++) {
for (int j = 0; j < length; j++)
if (i != j && s.charAt(i) == s.charAt(j))
continue L;
return i;
}
return -1;
}
public static void main(String[] args) {
System.out.println(firstUniqChar("leetcode"));
System.out.println(firstUniqChar("loveleetcode"));
System.out.println(firstUniqChar("aabb"));
}
output:
0
2
-1
you can use a flag variable.
public int firstUniqChar(String s) {
int flag=0;
for(int i=0;i<s.length();i++){
flag=0;
for(int j=0;j<s.length();j++){
if(s.charAt(i)==s.charAt(j) && i!=j){
flag=1;
break;
}
}
if(flag==0){
return i;
}
}
return -1;
}
There are 26 possible lowercase English letters, so you could use two 26 element arrays.
One array, letterCount, keeps counts of each letter. Start at 0 and add 1 every time the corresponding letter appears in the text string. The second array, position, holds the position of the first occurrence of that letter, or -1 if the letter never appears. You will need to initialise that array to -1 for all elements.
Process the string in order, recording initial positions, once only for each letter, and incrementing the count for each letter in the string.
After the string has been processed, look through the letterCount array. If there are no letters with a 1 count then return -1. If exactly one letter has a 1 count, then return the position of that letter from the position array. If more than one letter has a 1 count, then pick the one with the lowest value for its position.
Using two loops is a highly inefficient way of solving this problem. The string can be up to 100,000 characters long and you are processing it multiple times. Far better to process it only once, keeping track of what you have found so far.
Fix you code
You need to add a variable that tells you if you have breaked the loop or not
static int firstUniqChar(String s) {
boolean duplicate;
for (int i = 0; i < s.length(); i++) {
duplicate = false;
for (int j = i + 1; j < s.length(); j++) {
if (s.charAt(i) == s.charAt(j)) {
duplicate = true;
break;
}
}
if (!duplicate) {
return i;
}
}
return -1;
}
Improve
There is a smarter way, that is finding the last index occurence of the current char, if it's equal to the current index : that char is unique and you return its index
static int firstUniqChar(String s) {
for (int i = 0; i < s.length(); i++) {
if (s.lastIndexOf(s.charAt(i)) == i) {
return i;
}
}
return -1;
}
If you do not bother about time complexity using IdenxOF operations, then one can try this solution.
indexOf() – also runs in linear time. It iterates through the internal array and checking each element one by one. So the time
complexity for this operation always requires O(n) time.
int firstUniqCharOneLoop(String str) {
for (int i = 0; i < str.length(); i++) {
if (str.indexOf(str.charAt(i))== str.lastIndexOf(str.charAt(i)) ) {
return i;
}
}
return -1;
}
The lowest complexity I managed to achieve:
public class UniqueSymbolFinder {
static int findFirstUniqueChar(String s) {
Set<Character> set = new HashSet<>(s.length());
List<CharWithIndex> candidates = new LinkedList<>();
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
CharWithIndex charWithIndex = new CharWithIndex(ch, i);
if (set.add(ch)) {
candidates.add(charWithIndex);
} else {
candidates.remove(charWithIndex);
}
}
return candidates.size() == 0 ? -1 : candidates.get(0).index;
}
/**
* Class for storing the index.
* Used to avoid of using an indexOf or other iterations.
*/
private static class CharWithIndex {
int index;
char ch;
private CharWithIndex(char ch, int index) {
this.ch = ch;
this.index = index;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CharWithIndex that = (CharWithIndex) o;
return ch == that.ch;
}
#Override
public int hashCode() {
return Objects.hash(ch);
}
}
}
I believe the memory usage can still be optimized.
100% Correct JAVA Solution
Since the question is about returning the index of the first non-repeating character in a string, we need some data structure to save the index of each character in the string for us.
I choose here the HashMap of Java. Basically, what you can do with it, you can save a pair of values (or pair of other data structures).
So, in my solution, I am saving a Character Integer pair. The first is considered as a key (here it is each character in the string), and the second is its index value.
The problem here is that we only want to keep the minimum index of non-repeating characters and that's why if you take a look below, you will find the maxIndexForRepeatedValues is set to be 10 power 5 as the input constraint says 1 <= s.length <= 10 power 5.
However, I am using that value to neglect repeated characters that would be found in the HashMap and at the end, we retrieve the minimum index which is the index of course for the first character from the map, or if there were only repeated characters, we return -1.
To make the code shorter, I used ternary-operator but you can write it with if-else if you want!
class Solution {
public int firstUniqChar(String s) {
int maxIndexForRepeatedValues = 100000;
Map<Character, Integer> map = new HashMap<>();
for (int i = 0 ; i < s.length() ; i++) {
char key = s.charAt(i);
int resIndex = map.containsKey(key) ? maxIndexForRepeatedValues : i;
map.put(key, resIndex);
}
int minIndex = Collections.min(map.values());
return minIndex == maxIndexForRepeatedValues ? -1 : minIndex;
}
}

Sum odd numbers program

I'm writing a program where I'm supposed to make a method that calculates if the passed number is odd. For this method, I also need to check that passed number is > 0, and if not, return false.
I am also supposed to make a second method with two parameters (start and end, which represents a range of numbers) and the method is supposed to use a for loop to sum all odd numbers within that range. The parameter end needs to be greater than or equal to start and both start and end parameters have to be greater than 0.
If those conditions are not satisfied return -1 from the method to indicate invalid input.
This is the assignment:
Write a method called isOdd with an int parameter and call it number. The method needs to return a boolean.
Check that number is > 0, if it is not return false.
If number is odd return true, otherwise return false.
Write a second method called sumOdd that has 2 int parameters start and end, which represent a range of numbers.
The method should use a for loop to sum all odd numbers in that range including the end and return the sum.
It should call the method isOdd to check if each number is odd.
The parameter end needs to be greater than or equal to start and both start and end parameters have to be greater than 0.
If those conditions are not satisfied return -1 from the method to indicate invalid input.
I've tried for over an hour now but I'm not doing it correctly because my output is wrong. I've written down the expected results and my results below my code.
This is my code:
public static boolean isOdd(int number){
boolean status = false;
if(number < 0){
status = false;
} else if(number % 2 != 0){
status = true;
}
return status;
}
public static int sumOdd(int start, int end){
int sum = 0;
if((end < start) || (start < 0) || (end < 0)){
return -1;
}
for(int i = 0; i <= end; i++){
if((isOdd(i))){
sum += i;
}
}
return sum;
}
The expected result is:
System.out.println(sumOdd(1, 100));// → should return 2500
System.out.println(sumOdd(-1, 100)); // → should return -1
System.out.println(sumOdd(100, 100));// → should return 0
System.out.println(sumOdd(13, 13));// → should return 13 (This set contains one number, 13, and it is odd)
System.out.println(sumOdd(100, -100));// → should return -1
System.out.println(sumOdd(100, 1000));// → should return 247500
My result:
2500
-1
2500
49
-1
250000
First, your isOdd method only needs to return true if two conditions are met: the number must be greater than zero and it must be odd. That can be done with a single return and a boolean and. Like,
public static boolean isOdd(int number) {
return number > 0 && number % 2 != 0;
}
Second, your loop should start at start (not zero). But, I would then test if start is even. If it is, increment it before the loop. Then we know we have an initial value that is odd so we no longer need to test for oddness in the loop (we can increment by two instead). Like,
public static int sumOdd(int start, int end) {
if (end < start || start < 0 || end < 0) {
return -1;
}
int sum = 0;
if (!isOdd(start)) {
start++;
}
for (int i = start; i <= end; i += 2) {
sum += i;
}
return sum;
}
Which should be quite a bit more efficient.
Don't declare variables at the begging of your method, only create them when they are needed. As pointed out by Jordan the problem is with for loop index, it should start from start, not 0:
public static boolean isOdd(int number) {
if (number < 0) {
return false;
}
return number % 2 != 0;
}
public static int sumOdd(int start, int end) {
if ((end < start) || (start < 0) || (end < 0)) {
return -1;
}
int sum = 0;
for (int i = start; i < end; i++) {
if (isOdd(i)) {
sum += i;
}
}
return sum;
}

Return the count how many digits are 7 in the given number n

I'm writing a method for my CS151 class called countSevens(n). It Returns count how many digits are 7 in the given number n. This is what I have so far but I'm doing something wrong that I can't figure out.
public int countSevens(int n){
int count = 0;
String strI = Integer.toString(n);
for (int i = 0; i < strI.length(); i++){
if(strI.substring(i).equals("7")){
count++;
}
}
return count;
}
You can do it with java streams
public int countSevens(int n) {
return (int) String.valueOf(n).chars().filter(ch -> ch == '7').count();
}
(int) - cast to an int type, in this particular case it safe to cast long to int, because we can't get a conversation error. In other cases it's better to use Math.toIntExact(long)
String.valueOf(n) - convert to string
chars() - return stream of chars
filter(ch -> ch == '7') - filter all chars that equals to 7
count() - returns the count of elements in this stream
strI.substring(i)
Will return the part of string from i-character to the end.
Use strI.charAt(i) instead
From the definition of String.substring(int):
Returns a string that is a substring of this string. The substring begins with the character at the specified index and extends to the end of this string.
So this will only count the last instance of a 7 in your number, and only if it's the last digit in the number.
Instead, try this:
if(strI.substring(i, i+1).equals("7"))
Or, since you're dealing with ints, you can avoid using strings altogether. n % 10 will get you the last digit, and n /= 10 will bump the entire number right by one digit. That should be enough to get you started on doing this without Strings.
To count the number of 7s in an integer:
int counter = 0;
int number = 237123;
String str_number = String.valueOf(number);
for(char c : str_number.toCharArray()){
if(c == '7'){
counter++;
}
}
You can just use simple arithmetics:
public static int countSevens(int i) {
int count = 0;
for (i = i < 0 ? -i : i; i != 0; count += i % 10 == 7 ? 1 : 0, i /= 10);
return count;
}
But who can read this? Not many, so here is a cleaner solution, applying the same logic:
public static int countSevens(int i) {
int count = 0;
// ignore negative numbers
i = Math.abs(i);
while(i != 0) {
// if last digit is a 7
if(i % 10 == 7) {
// then increase the counter
count++;
}
// remove the last digit
i /= 10;
}
return count;
}

Any efficient way to determine there is more N continuous true in a boolean array? In Java

Example:
I have a boolean array with N boolean inside. Which is the most efficient way to determine there are more than continuous M true flags, in the array?
Write some thing like (bA=booleanArray, for M=3)
(bA[0] && bA[1] && bA[2]) || (bA[1] && bA[2] && bA[3]) || ...
is really ugly.
And this can not be done with a VERY-LONG dynamic length array with dynamic least true flags to meet need. And maybe inefficient with few and scattered true?
Use a loop and a counter:
int count = 0;
for (boolean x: theArray){
if (x) {
count++;
if (count >= n) return true; // n is the count we are looking for
} else { count = 0; }
}
return false;
This is one approach, that allows for adjusting the number of consecutive entries, and the array is not fixed in length. The method hasConsecutiveTrue will loop over the array, looking for a value of true. If found, it increments the counter, otherwise sets it to 0. If the counter matches the expected amount, it returns true. Otherwise, it will return false. EDIT: based upon a comment, make so it will throw an IllegalArgumentException for an attempt to find <= 0 consecutive numbers, or if the input array is null/empty.
public static void main(String[] args)
{
int consecutive = 3;
boolean[] ba = new boolean[] { true, false, true, true, true, false};
System.out.println("found: " + hasConsecutiveTrue(ba, consecutive));
}
private static boolean hasConsecutiveTrue(boolean[] ba, int consecutive) throws IllegalArgumentException
{
// we will not attempt to process if the input <= 0; if 0 should return
// true, then modify the conditional statement as appropriate
if (consecutive <= 0) {
throw new IllegalArgumentException("Invalid input for consecutive: " +
consecutive);
}
if (ba == null || ba.length < 1) {
throw new IllegalArgumentException("No array to check!");
}
int count = 0;
boolean found = false;
for (boolean b : ba) {
count = ( b ? count + 1 : 0);
if (count == consecutive) {
found = true;
break;
}
}
return found;
}
Here's one using BitSet: if you're able to start with a BitSet, it will almost certainly be more efficient. If you have to convert from a boolean[] or byte[], it might not be.
// BitSet bits = BitSet.valueOf(bA);
int i = bits.nextSetBit(0);
while (i > -1 && i < bits.length()) {
int nextFalse = bits.nextClearBit(i);
if (nextFalse - nextTrue > N) return true;
i = bits.nextSetBit(nextFalse) + 1;
}
return false;
One option is to use a string with T + F in the location to determine the true/false setting of your array. Then use contains.
Example:
String booleanArray = "TTFFTFTFTFTTTFFT";
if ( !booleanArray.contains("TTT") ) // Pattern was found.

count uppercase chars in string recursively

I have to solve an exercise, counting all the uppercase chars in a String - recursively - Anyhow I thought I might have found a solution - but it won't work…
Probably you might help me? Thanks!
public static int CountCapitals(String s) {
int counter = 0;
// if (Character.isUpperCase(s.charAt(0)))counter+=1;
if (s.length() == 0)
return counter;
if (s.length() == 1 && s.charAt(0) < 65 && s.charAt(0) > 90)
return 0;
if (s.charAt(0) < 'A' && s.charAt(0) > 'Z') {
return CountCapitals(s.substring(1));
}
if (s.charAt(0) >= 'A' && s.charAt(0) <= 'Z')
counter++;
return CountCapitals(s.substring(1));
}
The problem with your code is the use of counter: each level of invocation has its own counter, initially set to zero. The ++ operator at the bottom has no effect.
You need to compute the result of this invocation based on the result of the previous invocation. Your base case (i.e. s.length() == 0) is fine; the rest of your code needs to change so that it returns whatever CountCapitals(s.substring(1)) when the first letter is non-capital; when the first letter is capital, your function should return 1 + CountCapitals(s.substring(1)).
You need to consider the case when the length of string is 1 and the only character is uppercase (in this case, you should return 1).
Also you need to pass in the counter as a parameter rather than expecting it to "carry over" into other function calls.
This recursion should do just what you want:
public static int countCapitals(String s) {
if (s.length() == 0) return 0;
int cap = Character.isUpperCase(s.charAt(0)) ? 1 : 0;
return countCapitals(s.substring(1)) + cap;
}
If this wasn't a home assignment, you could try an iterative approach which is about 5-10 times faster:
public static int countCapitals(String s) {
int count = 0;
for (int idx = 0; idx < s.length(); idx++) {
if (Character.isUpperCase(s.charAt(idx))) {
count++;
}
}
return count;
}
You don't really need to use a counter variable to keep track of the number of capitals. Instead, you can just the recursive calls, themselves, to keep track of the total:
public static int CountCapitals(String s)
{
if (s.length() == 1)
return (Character.isUpperCase(s.charAt(0)) ? 1 : 0);
else
return CountCapitals(s.substring(1)) +
(Character.isUpperCase(s.charAt(0)) ? 1 : 0);
}
If this is for an assignment and you have to use ASCII values, then fine, but if not, you really should just Character.isUpperCase(char c). In case you're not familiar with the conditional operator, it's defined as follows:
if(someExpression == true)
{
//output 1
}
else
{
//output 0
}
is represented succinctly as:
(someExpression == true) ? 1 : 0
NB:
In your example, counter is set to 0 at the beginning of each method call, so that's why it's not working. If you really want to use a counter, pass it as a parameter to the method instead, and update the parameter with each method call. When you get to the end of the String, simply return the parameter.
You try this
public class HelloWorld{
public static int isUpperCase(String str){
if(str.length()==0) return 0;
boolean check =Character.isUpperCase(str.charAt(0));
if(check){
return isUpperCase(str.substring(1))+1;
}
return isUpperCase(str.substring(1));
}
public static void main(String []args){
String n= "FSAsdsadASdcCa";
System.out.println(isUpperCase("FSAsdsadASdcCa"));
}
}

Categories

Resources