In a recent interview, I was asked this to find the length of the longest sub-string with no consecutive repeating characters. This is different from the standard question, since it considers only consecutive repeating characters.
For example :
WOOD : 2
Italics : 7
This, of course, has to be done in O(N) time and space.
Go down the string character by character. Keep track of how many characters you've advanced without hitting a repeat in a var say "repeatcounter". If the next character matches the current character record the counter in a separate variable (only if it's bigger than what's already in there) and reset the repeatcounter.
In Python, I would approach it like this:
def interview(s):
current = longest = 0
for index, char in enumerate(s):
if index and char == s[index - 1]:
longest, current = max(longest, current), 0
current += 1
return max(longest, current)
public static void main(String[] args){
String s = "italics";
char[] c = s.toCharArray();
int tmp = 1;
for (int i = 1; i < s.length(); i++) {
if (c[i] == c[i-1]){
tmp = 0;
continue;
}
tmp++;
}
System.out.println(tmp);
}
output = 1
s = "italics"
output = 7
Hope the below code helps you. Thanks.
import java.util.HashSet;
public class SubString {
public static String subString(String input){
HashSet<Character> set = new HashSet<Character>();
String longestOverAll = "";
String longestTillNow = "";
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (set.contains(c)) {
longestTillNow = "";
set.clear();
}
longestTillNow += c;
set.add(c);
if (longestTillNow.length() > longestOverAll.length()) {
longestOverAll = longestTillNow;
}
}
return longestOverAll;
}
public static void main(String[] args) {
String input = "kaveeshkanwal abcvdghytrqp";//"substringfindout";
System.out.println(subString(input));
}
}
Related
I am trying to print all the unique characters from a string but I am not getting proper output. Also, I want to check if someone enters integer in string, I want to print Invalid String. How can I achieve this?
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
char[] ch = new char[20];
System.out.println("Enter the sentence:");
String sent = sc.nextLine().replaceAll(" ", "");
int count = 0;
for (int i = 0; i < sent.length(); i++) {
int j = (sent.length() - 1);
count = 0;
while (j > i) {
if (sent.charAt(j) == sent.charAt(i)) {
sent = deleteCharAt(sent, i);
sent = deleteCharAt(sent, j - 1);
break;
}
j--;
}
}
for (int i = 0; i < sent.length(); i++) {
System.out.println(sent.charAt(i));
}
}
private static String deleteCharAt(String strValue, int index) {
return strValue.substring(0, index) + strValue.substring(index + 1);
}
Enter the sentence:
java is good object oriented programming language
a
v
i
s
o
d
b
c
r
e
e
d
p
g
m
m
n
l
u
You are probably going to want to use a Set. These data structures are like Lists, except:
They do not have an ordering (meaning you cant call set.get(3))
They do not allow duplicates
You can think of them as a Map without any values.
If you have a String and you want to get all the unique chars from it. The steps are as follows:
String string = "hello"; // 4 unique characters
Set<Character> uniqueChars = new HashSet<>(); // create an empty set to put the unique chars into
// split into char[]
char[] chars = string.toCharArray();
Arrays.stream(chars).forEach(c -> {
// the following code will be run once for every char in the array
uniqueChars.add(c);
// adding the same char twice does not insert it twice
});
This can be written more concisely as:
String string = "hello";
Set<Character> uniqueChars = new HashSet<>();
Arrays.stream(string.toCharArray()).forEach(uniqueChars::add); // using a Java 8 method reference
If you want to reject any char that is a numerical digit, you can use the following line:
boolean containsDigit = Arrays.stream(string.toCharArray())
.filter(Character::isDigit) // filter out all the non digit characters
.findAny() // check if there are any remaining
.isPresent();
It would be more efficient and easier to read code to use a HashSet:
HashSet<Character> h = new HashSet<Character>();
for (int i = 0; i <= (sent.length() - 1); i++)
h.add(sent.charAt(i));
Iterator<Character> i = h.iterator();
while (i.hasNext())
System.out.println(i.next());
To avoid duplicate you can use a Set: is a collection that doesn't allow duplicates. You have to use a specific implementation of that interface, such as HashSet. You can do something like this:
public class UniqueChar {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter the sentence:");
String withoutSpaces = sc.nextLine();
withoutSpaces = "asc34csf"; // mock example
Set<Character> goodChars = new HashSet<>();
String sent = withoutSpaces.replaceAll(" ", "");
int count = 0;
for (int i = 0; i < sent.length(); i++) {
char currChar = sent.charAt(i);
// do not add a character if is a digit
if(Character.isDigit(currChar))
System.out.println("Digit!");
else
goodChars.add(currChar); // add a character only if not present
}
String output = "";
for (Character character : goodChars) {
output += character; // concat in a single output string
}
System.out.println(output);
}
So you simply jump characters that are digits, if it's a character it'll be added to the collection (and the Set manages internally the fact that if it's a duplicate, it will not be added), then concat the elements of the Set in a single String.
You can find more information about HashSet in the Java documentation.
You can write your code something like this:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[] alpha = new int[26];
System.out.println("Enter the sentence:");
String sent = sc.nextLine().replaceAll(" ", "");
for (int i = 0; i < sent.length(); i++) {
int temp = sent[i] - 'a';
if (temp >= 0 && temp <= 25) {
alpha[temp] = 1;
} else {
System.out.println("Invalid String");
return;
}
}
for (int i = 0; i < 26; i++) {
if (alpha[i] == 1)
System.out.println((char) (i + 'a'));
}
}
This uses an array of length 26 as the workaround if you don't want to use any SET like data structure.
This code can bring you problem if your sentence have capital letters as well. You can avoid that problem by using toLowercase like function just before the loop.
Question:
Write a function to find the longest common prefix string among an array of strings. If there is no common prefix, return an empty string "".
Example 1:
Input: ["flower","flow","flight"]
Output: "fl"
Example 2:
Input: ["dog","racecar","car"]
Output: ""
Explanation: There is no common prefix among the input strings.
Code:
public class Solution {
public String longestCommonPrefix(String[] strs) {
if(strs==null || strs.length==0)
return "";
for(int i=0;i<strs[0].length();i++) {
char x = strs[0].charAt(i);
for(int j=0;j<strs.length;j++) {
if((strs[j].length()==i)||(strs[j].charAt(i)!=x)) {
return strs[0].substring(0,i);
}
}
}
return strs[0];
}
}
This is the second solution, but I don't understand the inner loop.
I think if the second element in strs returns a string and ends the for loop, the third element will not have a chance to be compared.
You have to check same position in all of the words and just compare it.
positions
word 0 1 2 3 4 5
=====================
w[0] F L O W E R
w[1] F L O W
w[2] F L I G H T
In Java:
class Main {
public static void main(String[] args) {
String[] words = {"dog","racecar","car"};
String prefix = commonPrefix(words);
System.out.println(prefix);
// return empty string
String[] words2 = {"dog","racecar","car"};
String prefix2 = commonPrefix(words2);
System.out.println(prefix2);
// Return "fl" (2 letters)
}
private static String commonPrefix(String[] words) {
// Common letter counter
int counter = 0;
external:
for (int i = 0; i < words[0].length(); i++) {
// Get letter from first word
char letter = words[0].charAt(i);
// Check rest of the words on that same positions
for (int j = 1; j < words.length; j++) {
// Break when word is shorter or letter is different
if (words[j].length() <= i || letter != words[j].charAt(i)) {
break external;
}
}
// Increase counter, because all of words
// has the same letter (e.g. "E") on the same position (e.g. position "5")
counter++;
}
// Return proper substring
return words[0].substring(0, counter);
}
}
Your first loop is itterating over all chars in the first string of array. Second loop is checking char at i posistion of all strings of array. If characters do not match, or length of string is the same as i it returns substring result.
I think the best way to understand is debug this example.
If the char in the second string is different than the char in the first one, then it is correct to return, since it means that the common prefix ends there. Checking the third and following strings is not necessary.
Basically it returns as soon as it finds a mismatch char.
If we first sort them then it would be very easy we have to only go and compare the first and the last element in the vector present there so,
the code would be like,This is C++ code for the implementation.
class Solution {
public:
string longestCommonPrefix(vector<string>& str) {
int n = str.size();
if(n==0) return "";
string ans = "";
sort(begin(str), end(str));
string a = str[0];
string b = str[n-1];
for(int i=0; i<a.size(); i++){
if(a[i]==b[i]){
ans = ans + a[i];
}
else{
break;
}
}
return ans;
}
};
public class Solution {
public string LongestCommonPrefix(string[] strs) {
if(strs.Length == 0)
{
return string.Empty;
}
var prefix = strs[0];
for(int i=1; i<strs.Length; i++) //always start from 1.index
{
while(!strs[i].StartsWith(prefix))
{
prefix = prefix.Substring(0, prefix.Length-1);
}
}
return prefix;
}
}
Please help me to identify my mistakes in this code. I am new to Java. Excuse me if I have done any mistake. This is one of codingbat java questions. I am getting Timed Out error message for some inputs like "xxxyakyyyakzzz". For some inputs like "yakpak" and "pakyak" this code is working fine.
Question:
Suppose the string "yak" is unlucky. Given a string, return a version where all the "yak" are removed, but the "a" can be any char. The "yak" strings will not overlap.
public String stringYak(String str) {
String result = "";
int yakIndex = str.indexOf("yak");
if (yakIndex == -1)
return str; //there is no yak
//there is at least one yak
//if there are yaks store their indexes in the arraylist
ArrayList<Integer> yakArray = new ArrayList<Integer>();
int length = str.length();
yakIndex = 0;
while (yakIndex < length - 3) {
yakIndex = str.indexOf("yak", yakIndex);
yakArray.add(yakIndex);
yakIndex += 3;
}//all the yak indexes are stored in the arraylist
//iterate through the arraylist. skip the yaks and get non-yak substrings
for(int i = 0; i < length; i++) {
if (yakArray.contains(i))
i = i + 2;
else
result = result + str.charAt(i);
}
return result;
}
Shouldn't you be looking for any three character sequence starting with a 'y' and ending with a 'k'? Like so?
public static String stringYak(String str) {
char[] chars = (str != null) ? str.toCharArray()
: new char[] {};
StringBuilder sb = new StringBuilder();
for (int i = 0; i < chars.length; i++) {
if (chars[i] == 'y' && chars[i + 2] == 'k') { // if we have 'y' and two away is 'k'
// then it's unlucky...
i += 2;
continue; //skip the statement sb.append
} //do not append any pattern like y1k or yak etc
sb.append(chars[i]);
}
return sb.toString();
}
public static void main(String[] args) {
System.out.println(stringYak("1yik2yak3yuk4")); // Remove the "unlucky" strings
// The result will be 1234.
}
It looks like your programming assignment. You need to use regular expressions.
Look at http://www.vogella.com/articles/JavaRegularExpressions/article.html#regex for more information.
Remember, that you can not use contains. Your code maybe something like
result = str.removeall("y\wk")
you can try this
public static String stringYak(String str) {
for (int i = 0; i < str.length(); i++) {
if(str.charAt(i)=='y'){
str=str.replace("yak", "");
}
}
return str;
}
The question is to generate the lexicographically greatest string given some string s.
So the aim is to find lexicographically greatest, unique(no repetitions) substring s1 from s.
We say that some subsequence s1 is greater than another subsequence s2 if s1 has more characters than s2 or s1 is lexicographically greater than s2 if equal length.
I/O are as follows:
Input is: babab
output is: ba
Second input is: nlhthgrfdnnlprjtecpdrthigjoqdejsfkasoctjijaoebqlrgaiakfsbljmpibkidjsrtkgrdnqsknbarpabgokbsrfhmeklrle
Second output is:
tsocrpkijgdqnbafhmle
This is what I wrote for my java code but my code fails on the second test case. Also I'm having a hard time understanding why second output isn't tsrqponmlkjihgfedcba.
Can somebody provide suggestions for a fix or even java code?
I think the algorithm has to be more efficient than generating all possible unique strings, sort them and find lexicographically largest one.
To make the question much clearer, if the input is babab, then all the possible unique combinations would be b, a, ba, ab. And the output will be ba because it's the longest and lexicographically greater than ab.
Note: this is not a homework assignment.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class mostBeautiful {
final static int MAX = 1000000;
static String[] permute;
static void permutation(String prefix, String str, int counter) {
int n = str.length();
//System.out.println("n is: "+ n);
if (n == 0) {
permute[counter] = prefix;
} else {
for (int i = 0; i < n; i++) {
//System.out.println("str is: "+ str);
permutation(prefix + str.charAt(i), str.substring(0, i) + str.substring(i+1, n), counter++);
}
}
}
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String s = bf.readLine();
char[] unique = new char[26];
int counter = 0;
String answer = "";
//System.out.println("s is: " + s);
int ascii = 0;
final int asciiAVal = 97;
final int asciiZVal = 122;
for (int i = 0; i < s.length(); i++) {
ascii = (int)s.charAt(i);
if (ascii < asciiAVal || ascii > asciiZVal) {
continue;
}
char ch = s.charAt(i);
unique[ch - 'a'] = ch;
}
String result = "";
for (int j = 25; j >= 0; j--) {
result += unique[j];
}
result = result.trim();
System.out.println(result);
int size = result.length() * (result.length() - 1);
permute = new String[size];
permutation("", result, counter);
for (int i = 1; i < size; i++) {
if (permute[i].compareTo(permute[i - 1]) > 0){
answer = permute[i];
} else {
answer = permute[i - 1];
}
}
System.out.println("answer is: " + answer);
}
}
After thinking about this problem in many ways, I have determined a divide-and-conquer algorithm that gets the results right:
Algorithm - Pseudocode
Assuming some input string, S defined as a concatenation of two substrings A + B, we compute the lexicographically greatest string recursively as:
LexMax(S) = Merge(LexMax(A),LexMax(B))
Where
LexMax(S)
{
if Length(S) = 1
return S
else
{
LMA = LexMax(S[0:Length/2])
LMB = LexMax(S[Length/2:end])
return Merge(LMA,LMB)
}
}
Merge(A,B)
{
Sa = A
Sb = B
for n = 0:Length(A)
{
if Sb contains A[n]
{
if A[n+1:end] contains character > A[n]
Remove A[n] from Sa
else
Remove A[n] from Sb
}
}
return Sa + Sb
}
Java Code
Coming soon!
Example
Given an input string
cefcfdabbcfed
Divide it into
cefcfda
bbcfed
Assuming the function works we have:
LexMax("cefcfda") = "efcda"
LexMax("bbcfed") = "bcfed"
Merging works as follows:
e: efcda bcfed
In both substrings, greater value found to right of e in left substring, remove from left
f: fcda bcfed
In both substrings, no greater value in left substring, remove from right
c: fcda bced
In both substrings, greater value found to right of c in left substring, remove from left
d: fda bced
In both substrings, no greater value in left substring, remove from right
a: fda bce
Not in both substrings, do nothing
Final result:
LexMax(cefcfdabbcfed) = fdabce
This is not a direct answer, but doesn't this code meet the requirement as you explained it in the discussion above?
final String x = "saontehusanoethusnaoteusnaoetuh";
final SortedSet<Character> chars =
new TreeSet<Character>(Collections.reverseOrder());
for (char c : x.toCharArray()) chars.add(c);
System.out.println(chars);
Lexicographic order is an order in which words are displayed in alphabetical order using the appearance of letters in the word.It is also know as dictionary order or alphabetical order.For ex:-"Africa" is smaller than "Bangladesh" ,"He" is smaller than "he".
public class LexicographicExample {
public static void main(String a[]) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter the String:-");
String str = sc.nextLine();
System.out.println("Enter the length");
int count = sc.nextInt();
List<String> list = new ArrayList<String>();
for (int i = 0; i < str.length(); i = i + 1) {
if (str.length() - i >= count) {
list.add(str.substring(i, count + i));
}
}
Collections.sort(list);
System.out.println("Smallest subString:-" + list.get(0));
System.out.println("Largest subString:-" + list.get(list.size() - 1));
}
}
For reference ,refer this link http://techno-terminal.blogspot.in/2015/09/java-program-to-find-lexicographically.html
"tsrqponmlkjihgfedcba" is not the answer because it is not a subsequence of the input. The definition of subsequence requires that the characters of the subsequence occur in the original sequence in the same order. For example, "abc" is a subsequence of "apbqcr", while "cba" is not.
As to the solution, I think a simple greedy algorithm would suffice. First, one has to understand that the maximum possible length of the output is the number of unique symbols (say, N) in the input. Since any output shorter than that would not be the greatest one, it has to be exactly N symbols long. The rest of the procedure is simple and at most quadratic in time complexity: one has to go through the input string and at each step pick the lexicographically highest symbol such that the part of the string to the left of it would still contain all the "unused" symbols.
As an example, consider a string "bacb". The first symbol can be 'a' or 'b', since in both cases the remainder contains both of the other letters. 'b' is greater, so we pick it. Now for "acb" we can only pick 'a' and than 'c' according to that condition, so we end up with "bac" for output.
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;
class aaa {
public static void main(String args[]) throws Exception {
Scanner scan = new Scanner(System.in);
// int n = scan.nextInt();
String s = scan.next();
HashMap<Character, Node5> map = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
if (!map.containsKey(s.charAt(i))) {
Node5 node = new Node5();
node.nl.add(i);
node.li = i;
map.put(s.charAt(i), node);
} else {
Node5 rn = map.get(s.charAt(i));
rn.nl.add(i);
rn.li = i;
map.put(s.charAt(i), rn);
}
}
String s1 = "";
int index = -1;
for (int i = 25; i >= 0; i--) {
if (map.containsKey((char) (97 + i))) {
if (map.get((char) (97 + i)).li > index) {
for (int j = 0; j < map.get((char) (97 + i)).nl.size(); j++) {
if (map.get((char) (97 + i)).nl.get(j) > index) {
s1 += (char) (97 + i);
index = map.get((char) (97 + i)).nl.get(j);
}
}
}
}
}
System.out.println(s1);
scan.close();
}
}
class Node5 {
int li;
ArrayList<Integer> nl;
public Node5() {
this.nl = new ArrayList<>();
}
}
What I am trying to do, is create a method, that has a string and a character as parameters, the method then takes the string and searches for the given character. If the string contains that character, it returns an array of integers of where the character showed up. Here is what I have so far:
public class Sheet {
public static void main(String[] args) {
String string = "bbnnbb";
String complete = null;
//*******
for(int i = 0; i < string.length(); i++){
complete = StringSearch(string,'n').toString();
}
//********
}
public static int[] StringSearch(String string, char lookfor) {
int[]num = new int[string.length()];
for(int i = 0; i < num.length; i++){
if(string.charAt(i)== lookfor){
num[i] = i;
}
}
return num;
}
}
The method works fine, and returns this:
0
0
2
3
0
0
What I am trying to do, is make those into 1 string so it would look like this "002300".
Is there any possible way of doing this? I have tried to do it in the starred area of the code, but I have had no success.
just do
StringBuffer strBuff = new StringBuffer();
for(int i = 0; i<str.length(); i++)
{
if(str.charAt(i) == reqChar)
{
strBuff.append(str.charAt(i));
}
else
{
strBuff.append('0');
}
}
return str.toString();
Just add the result to the existing string with the += operator
String complete = "";
for(...)
complete += StringSearch(string,'n').toString();
I would just use java's regex library, that way it's more flexible (eg if you want to look for more than just a single character). Plus it's highly optimized.
StringBuilder positions = "";
Pattern pattern = Pattern.compile(string);
Matcher matcher = pattern.matcher(lookfor);
while(matcher.find()){
positions.append(matcher.start());
}
return positions;
Updated with StringBuilder for better practices.
public static String StringSearch(String string, char lookfor) {
StringBuilder sb = new StringBuilder();
for(int i = 0; i < string.length; i++){
if(string.charAt(i) == lookfor)
sb.append(i);
else
sb.append("0");
}
return sb.toString();
}
Then you can just call it once, without a for loop. Not sure why you call it for every character in the string.
complete = StringSearch(string,'n');