public static int findFreqWithMutations(String toFind, String[] list) {
int count = 0;
String mutation = "";
for (int i = 0; i < list.length; i++) {
//if there's a mutation, let's change it!
for (int j = 1; j < list[i].length(); j++) {
if (list[i].charAt(j - 1) == list[i].charAt(j)) {
mutation += "";
} else {
mutation += list[i].charAt(j - 1);
}
}
//list[i] = mutation + list[i].charAt(list[i].length() - 1);
mutation += list[i].charAt(list[i].length() - 1);
list[i] = mutation;
}
}
The code findFreqWithMutations(String to Find, String [] list) serves the purpose of scanning through a String array, String[] list = {"AAA", "ABC", "CDEE", "FGHH"}, and correcting mutations (mutations as in same character consecutively, so AAA would be A without mutation, and CDEE would be CDE without mutation).
My third last row: list[i] = mutation + list[i].charAt(list[i].length() - 1) work the way it should,
But NOT my last two lines of code..
Are they not the same?
I have made some changes, and the result is what you want:
re-initialize mutation for each string
test Char (j+1), then keep it
then finally, nothing to do
String[] list = {"AAA", "ABC", "CDEE", "FGHH"};
for (int i = 0; i < list.length; i++)
{
// MORE CLEAR
String source= list[i];
// PUT INSIDE
String mutation = "";
if (source.length()==0) continue; // if void
mutation+=source.charAt(0);
//if there's a mutation, let's change it!
for (int j = 1; j <source.length(); j++)
{
if (source.charAt(j - 1) == source.charAt(j))
mutation += "";
else
mutation += source.charAt(j); // Take this, not the precedent
}
list[i] = mutation;
}
Related
So I was grinding leetcode and came across a solution that looked like this. What does the syntax "search:" and "continue search;" do? I have never seen this syntax before when I write for-loop. Thanks in advance!
public boolean isAlienSorted(String[] words, String order) {
int[] index = new int[26];
for (int i = 0; i < order.length(); ++i)
index[order.charAt(i) - 'a'] = i;
search: for (int i = 0; i < words.length - 1; ++i) {
String word1 = words[i];
String word2 = words[i+1];
// Find the first difference word1[k] != word2[k].
for (int k = 0; k < Math.min(word1.length(), word2.length()); ++k) {
if (word1.charAt(k) != word2.charAt(k)) {
// If they compare badly, it's not sorted.
if (index[word1.charAt(k) - 'a'] > index[word2.charAt(k) - 'a'])
return false;
continue search;
}
}
// If we didn't find a first difference, the
// words are like ("app", "apple").
if (word1.length() > word2.length())
return false;
}
return true;
}
That's a label (see goto – similar to C), it's rather unnecessary here for solving the problem.
The following solution would simply get through:
class Solution {
int[] letterMap = new int[26];
public final boolean isAlienSorted(
final String[] words,
final String order
) {
for (int index = 0; index < order.length(); index++) {
letterMap[order.charAt(index) - 'a'] = index;
}
for (int index = 1; index < words.length; index++)
if (wordIsLarger(words[index - 1], words[index])) {
return false;
}
return true;
}
private final boolean wordIsLarger(
final String a,
final String b
) {
final int lengthA = a.length();
final int lengthB = b.length();
for (int index = 0; index < lengthA && index < lengthB; index++)
if (a.charAt(index) != b.charAt(index)) {
return letterMap[a.charAt(index) - 'a'] > letterMap[b.charAt(index) - 'a'];
}
return lengthA > lengthB;
}
}
If we would format it, we can see much easier:
public boolean isAlienSorted(String[] words, String order) {
int[] index = new int[26];
for (int i = 0; i < order.length(); ++i) {
index[order.charAt(i) - 'a'] = i;
}
search:
for (int i = 0; i < words.length - 1; ++i) {
String word1 = words[i];
String word2 = words[i + 1];
// Find the first difference word1[k] != word2[k].
for (int k = 0; k < Math.min(word1.length(), word2.length()); ++k) {
if (word1.charAt(k) != word2.charAt(k)) {
// If they compare badly, it's not sorted.
if (index[word1.charAt(k) - 'a'] > index[word2.charAt(k) - 'a'])
{ return false; }
continue search;
}
}
// If we didn't find a first difference, the
// words are like ("app", "apple").
if (word1.length() > word2.length()) {
return false;
}
}
return true;
}
This is labeled continue. This is mostly used when there are multilevel loops. And we want to continue to outer loop directly from inner loop.
Although it is highly recommended to avoid it.
I need to find all the permutations for a given n(user input) without backtracking.
What i tried is:
import java.util.Scanner;
import java.util.Vector;
class Main {
private static int n;
private static Vector<Vector<Integer>> permutations = new Vector<>();
private static void get_n() {
Scanner user = new Scanner(System.in);
System.out.print("n = ");
n = user.nextInt();
}
private static void display(Vector<Vector<Integer>> permutations) {
for (int i = 0; i < factorial(n) - 1; ++i) {
for (int j = 0; j < n; ++j) {
System.out.print(permutations.elementAt(i).elementAt(j) + " ");
}
System.out.println();
}
}
private static int factorial(int n) {
int result = 1;
for (int i = 1; i <= n; ++i) {
result *= i;
}
return result;
}
private static int max(Vector<Integer> permutation) {
int max = permutation.elementAt(0);
for (int i = 1; i < permutation.size(); ++i)
if (permutation.elementAt(i) > max)
max = permutation.elementAt(i);
return max;
}
// CHECKS FOR ELEMENT COUNT AND 0 - (n-1) APPARITION
public static int validate_permutation(Vector<Integer> permutation) {
// GOOD NUMBER OF ELEMENTS
if (max(permutation) != permutation.size() - 1)
return 0;
// PROPER ELEMENTS APPEAR
for (int i = 0; i < permutation.size(); ++i)
if (!permutation.contains(i))
return 0;
return 1;
}
private static Vector<Integer> next_permutation(Vector<Integer> permutation) {
int i;
do {
i = 1;
// INCREMENT LAST ELEMENT
permutation.set(permutation.size() - i, permutation.elementAt(permutation.size() - i) + 1);
// IN A P(n-1) PERMUTATION FOUND n. "OVERFLOW"
while (permutation.elementAt(permutation.size() - i) == permutation.size()) {
// RESET CURRENT POSITION
permutation.set(permutation.size() - i, 0);
// INCREMENT THE NEXT ONE
++i;
permutation.set(permutation.size() - i, permutation.elementAt(permutation.size() - i) + 1);
}
} while (validate_permutation(permutation) == 0);
// OUTPUT
System.out.print("output of next_permutation:\t\t");
for (int j = 0; j < permutation.size(); ++j)
System.out.print(permutation.elementAt(j) + " ");
System.out.println();
return permutation;
}
private static Vector<Vector<Integer>> permutations_of(int n) {
Vector<Vector<Integer>> permutations = new Vector<>();
// INITIALIZE PERMUTATION SET WITH 0
for (int i = 0; i < factorial(n); ++i) {
permutations.addElement(new Vector<>());
for(int j = 0; j < n; ++j)
permutations.elementAt(i).addElement(0);
}
for (int i = 0; i < n; ++i)
permutations.elementAt(0).set(i, i);
for (int i = 1; i < factorial(n); ++i) {
// ADD THE NEXT PERMUTATION TO THE SET
permutations.setElementAt(next_permutation(permutations.elementAt(i - 1)), i);
System.out.print("values set by permutations_of:\t");
for (int j = 0; j < permutations.elementAt(i).size(); ++j)
System.out.print(permutations.elementAt(i).elementAt(j) + " ");
System.out.println("\n");
}
System.out.print("\nFinal output of permutations_of:\n\n");
display(permutations);
return permutations;
}
public static void main(String[] args) {
get_n();
permutations.addAll(permutations_of(n));
}
}
Now, the problem is obvious when running the code. next_permutation outputs the correct permutations when called, the values are set correctly to the corresponding the vector of permutations, but the end result is a mass copy of the last permutation, which leads me to believe that every time a new permutation is outputted by next_permutation and set into the permutations vector, somehow that permutation is also copied over all of the other permutations. And I can't figure out why for the life of me.
I tried both set, setElementAt, and an implementation where I don't initialize the permutations vector fist, but add the permutations as they are outputted by next_permutation with add() and I hit the exact same problem. Is there some weird way in which Java handles memory? Or what would be the cause of this?
Thank you in advance!
permutations.setElementAt(next_permutation(permutations.elementAt(i - 1)), i);
This is literally setting the vector at permutations(i) to be the same object as permutations[i-1]. Not the same value - the exact same object. I think this the source of your problems. You instead need to copy the values in the vector.
My title isn't the best but i haven't any other ideas. I have one List of objects with a List categories parameter and one String. The String is something like: "action,azione adventure,avventura horror sport ". I have to split it with spaces to obtain an array of strings like: ["action,azione", "adventure,avventura", "horror", "sport"].
I have to remove an item from the List of objects if his List categories item isn't contained in the array of String.
I know that it could sound tricky so i'll make some example:
Array: ["action,azione", "adventure,avventura", "horror", "sport"]
List categories (of the actual List object): ["action", "adventure", "horror", "comic", "sport"] remain
Array: ["action,azione", "adventure,avventura", "horror", "sport"]
List categories (of the actual List object): ["azione", "horror", "comico", "sport"] delete because adventure categories isn't there
Here is my try:
listaManga.getManga() is the List of objects
listaManga.getManga().get(index).getC() is the List of categories of that object
String[] categories is the String splitted in spaces
String[] categories = MainActivity.categories.split(" ");
for (int i = 0; i < listaManga.getManga().size(); i++) {
for (int j = 0; j < categories.length; j++) {
for (int z = 0; z < listaManga.getManga().get(i).getC().size(); z++) {
if (!categories[j].contains(String.valueOf(listaManga.getManga().get(i).getC().get(z)))) {
listaManga.getManga().remove(i);
break;
}
}
}
}
It throws IndexOutOfBoundsException on j value.
See if the following works.
String[] categories = MainActivity.categories.split(" ");
boolean found = false;
for (int i = (listaManga.getManga().size() - 1); i >= 0; i--) {
found = false;
for (int j = (categories.length - 1); j >= 0; j--) {
for (int z = (listaManga.getManga().get(i).getC().size() - 1); z >= 0; z--) {
if (!categories[j].contains(String.valueOf(listaManga.getManga().get(i).getC().get(z)))) {
listaManga.getManga().remove(i);
// Either do this
// i = i - 1;
// or put a flag here that is
// found == true;
break;
}
//if(found == true){
// break;
//}
}
}
}
I finally solved it following the inverse loop cycle idea but i had to change the code of muasif80 cause his code take to an issue:
It can get right categories only if in listaManga.getManga().get(i).getC() there aren't more categories. I'll make an example: if i have ["comic", "adventure"] as String[] categories, it will find all list item with ["comic", "adventure"] categories but not also item with more other categories like: ["comic", "adventure", "horror"].
I did it setting a new String to check every possibility:
String is_contained = "";
String[] categories = MainActivity.categories.split(" ");
for (int i = (listaManga.getManga().size() - 1); i >= 0; i--) {
if(listaManga.getManga().get(i).getC().size()==0){
listaManga.getManga().remove(i);
} else {
for (int j = (categories.length - 1); j >= 0; j--) {
is_contained = "";
for (int z = (listaManga.getManga().get(i).getC().size() - 1); z >= 0; z--) {
if (!categories[j].toLowerCase().contains((String.valueOf(listaManga.getManga().get(i).getC().get(z))).toLowerCase())) {
is_contained += "a";
} else {
is_contained += "b";
}
}
if (!is_contained.toLowerCase().contains(("b").toLowerCase())) {
listaManga.getManga().remove(i);
break;
}
}
}
}
P.s. Also if this is the most correct answer, i'll accept the one of muasif80 for all the time that he dedicated to me in chat!
I want to take two strings and alternate the characters into a new string using a for method.
Example: "two" and "one"
Result: "townoe"
This is what I have so far, and I really don't know how to finish it.
public class Alternator {
String alternate(String a, String b) {
String s = "";
for (int i = 0; i < a.length(); i++) {
s += i;
System.out.println(s);
}
return null;
}
}
public class Alternator{
public static String alternate(String a, String b){
String s = "";
int i = 0;
while (i < a.length() && i < b.length()){
s += a.charAt(i) +""+ b.charAt(i);
i++;
}
while (i < a.length() ){
s += a.charAt(i);
i++;
}
while (i < b.length()){
s += b.charAt(i);
i++;
}
return s;
}
public static void main(String[] args){
String a = "two", b = "one";
String s = Alternator.alternate(a,b);
System.out.println(s);
}
}
To use for loop instead of while loop, simply remove all while lines with for lines like the following, then remove the i++ line from each while loop
for(; i < a.length() && i < b.length(); i++){
//the inside of the loop MINUS THE LINE i++
}
for(; i < a.length(); i++){
//the inside of the loop MINUS THE LINE i++
}
for(; i < b.length(); i++){
//the inside of the loop MINUS THE LINE i++
}
Here is some compact way of doing that:
String alternate(String a, String b) {
StringBuilder builder = new StringBuilder();
int smallerStringLength = Math.min(a.length(), b.length());
for (int i = 0; i < smallerStringLength; i++) {
builder.append(a.charAt(i));
builder.append(b.charAt(i));
}
return builder.toString();
}
Or even more optimized:
String alternate(String first, String second) {
char[] firstChars = first.toCharArray();
char[] secondChars = second.toCharArray();
int smallerCharsCount = Math.min(firstChars.length, secondChars.length);
StringBuilder builder = new StringBuilder(smallerCharsCount * 2);
for (int i = 0; i < smallerCharsCount; i++) {
builder.append(firstChars[i]);
builder.append(secondChars[i]);
}
return builder.toString();
}
This will work if string are of same length or of the different lengths.
static void mergeStrings(String a, String b) {
StringBuilder mergedBuilder = new StringBuilder();
char[] aCharArr = a.toCharArray();
char[] bCharArr = b.toCharArray();
int minLength = aCharArr.length >= bCharArr.length ? bCharArr.length : aCharArr.length;
for (int i=0; i<minLength; i++) {
mergedBuilder.append(aCharArr[i]).append(bCharArr[i]);
}
if(minLength < aCharArr.length) {
mergedBuilder.append(a.substring(minLength));
}
else{
mergedBuilder.append(b.substring(minLength));
}
Systemout.println(mergedBuilder.toString());
}
Assuming that the two strings are the exact same length, you can do the following. If they are different length, then currently your prompt doesn't say how you want the resultant string to be set up.
public class Alternator {
String alternate(String a, String b) {
String s = "";
for (int i = 0; i < 2*a.length(); i++) {
if (i%2==0) // modular arithmetic to alternate
s += a.charAt(i/2); // Note the integer division
else
s += b.charAt(i/2);
}
System.out.println(s);
return s;
}
}
Alternatively, even easier, but the index i doesn't mark the length of your string s:
public class Alternator {
String alternate(String a, String b) {
String s = "";
for(int i = 0; i < a.length(); i++){
s += a.charAt(i);
s += b.charAt(i);
}
return s;
}
}
Use this:
String alternate(String a, String b){
StringBuilder builder = new StringBuilder();
final int greaterLength = a.length() > b.length() ? a.length() : b.length();
for(int i = 0; i < greaterLength; i++){
if (i < a.length()) {
builder.append(a.charAt(i));
}
if (i < b.length()) {
builder.append(b.charAt(i));
}
}
return builder.toString();
}
It uses the String.charAt method to obtain letters, and a StringBuilder to create the string.
(When given two strings of non-equal length, this returns an alternation of the first two chars, and then does just the remaining string. EG: Hello and Hi --> HHeillo)
According to the comments I've read, you are having trouble understanding for loops, and how to use them with strings.
For loops are most often used to iterate over arrays, or to perform a task a given number of times.
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
This would give the output
0
1
2
3
4
For loops start at the value of the initializer, the first thing you put in int i = 0;
They then check the expression, the second part of the for loop, and if it returns true, it executes all of the code inside the braces. i < 5;
Once it has done that, it runs the incrementor, the last part of the for loop. i++
After that, it checks the expression again. I guess you can see where this is going. Until the expression returns false, everything inside the curly braces of the for loop gets executed over and over again.
Strings can be iterated over with a for loop, but you can't reference it like an array using array[index]. You have to either convert it into an array, using .toCharArray() on your String, and return the result to an empty char array char[], or use the .charAt(index) method on your string.
This code will go over a string, and output each character, one by one:
for (int i = 0; i < myString.length(); i++) {
System.out.println(myString.charAt(i));
}
If the string had a value of "Hello", the output would be:
H
e
l
l
o
Using this, instead of outputting the characters using System.out.println();, we can put them into an empty string, using +=:
myOtherString += myString.charAt(i);
That means, if we want to go over two Strings at a time, and alternate them, like you do, we can iterate over two strings at the same time, and add them to a new string:
myAlternatedString += myString.charAt(i);
myAlternatedString += myOtherString.charAt(i);
if MyString was still "Hello" and myOtherString was "World", the new string would be:
Hweolrllod
following code reads 2 different inputs and merges into a single string.
public class PrintAlternnateCharacterString {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String a = in.next();
String b = in.next();
String mergedString = "";
int lenA = a.length();
int lenB = b.length();
if (lenA >= lenB) {
for (int i = 0; i < lenA; i++) {
if (i < lenB) {
mergedString += a.charAt(i) + "" + b.charAt(i);
} else {
mergedString += a.charAt(i);
}
}
}
if (lenB > lenA) {
for (int i = 0; i < lenB; i++) {
if (i < lenA) {
mergedString += a.charAt(i) + "" + b.charAt(i);
} else {
mergedString += b.charAt(i);
}
}
}
System.out.println("the merged string is-->" + mergedString);
}
}
public static String stringConcate(String str1,String str2){
String str3="";
if(str1!=null && str2!=null && !str1.isEmpty() && !str2.isEmpty()){
if(str1.length()==str2.length()){
for(int i=0;i<=str1.length()-1;i++){
str3+=str1.charAt(i);
str3+=str2.charAt(i);
}
}
if(str1.length()>str2.length()){
for(int i=0;i<=str1.length()-1;i++){
str3+=str1.charAt(i);
if(i<str2.length()){
str3+=str2.charAt(i);
}
}
}
if(str2.length()>str1.length()){
for(int i=0;i<=str2.length()-1;i++){
if(i<str1.length()){
str3+=str1.charAt(i);
}
str3+=str2.charAt(i);
}
}
}
return str3;
}
String str1 = "one"; String str2 = "two";
StringBuilder sb = new StringBuilder();
int i = 0;
for (; i < str1.length() && i < str2.length(); i++) {
sb.append(str1.charAt(i)).append(str2.charAt(i));
}
for(; i < str1.length(); i++) {
sb.append(str1.charAt(i));
}
for(; i < str2.length(); i++) {
sb.append(str2.charAt(i));
}
System.out.println("result = " + sb.toString());// otnweo
This will handle for different length too
This could be donw with very simple if...else.
public static void main(String... args) {
int[] one = { 1, 2, 3 };
int[] two = { 44, 55, 66, 77, 88 };
System.out.println(Arrays.toString(alternate(one, two)));
}
public static int[] alternate(int[] one, int[] two) {
int[] res = new int[one.length + two.length];
for (int i = 0, j = 0, k = 0; i < res.length; i++) {
if (i % 2 == 0)
res[i] = j < one.length ? one[j++] : two[k++];
else
res[i] = k < two.length ? two[k++] : one[j++];
}
return res;
}
Output:
[1, 44, 2, 55, 3, 66, 77, 88]
Below code is from topcoder website. I was trying to figure the time complexity for this code. There is 1 for loop and 1 while loop in the method isRandom and 1 for loop in the method diff. I guess the worst case scenario would be O(n^2). Is that correct?
public class CDPlayer {
private boolean[] used;
public boolean diff(String str, int from, int to) {
Arrays.fill(used, false);
to = Math.min(to, str.length());
for (int i = from; i < to; i++) {
if (used[str.charAt(i) - 'A']) {
return false;
}
used[str.charAt(i) - 'A'] = true;
}
return true;
}
public int isRandom(String[] songlist, int n){
String str = "";
for (int i = 0; i < songlist.length; i++) {
str += songlist[i];
}
used = new boolean[26];
for (int i = 0; i < n; i++) {
if (!diff(str, 0, i)) {
continue;
}
int j = i;
boolean bad = false;
while (j < str.length()) {
if (!diff(str, j, j + n)) {
bad = true;
break;
}
j += n;
}
if (bad) {
continue;
}
return i;
}
return -1;
}
}
I figured out something like this O(S) + O(n^2) + O(SS)*O(n^2), where
S = songlist.length, SS = sum of all song lengths. So your complexity depends on various inputs and it can't be represented by simple value.
P.S. Note that String is immutable object, so better use StringBuilder.
Before:
String str = "";
for (int i = 0; i < songlist.length; i++) {
str += songlist[i];
}
After:
StringBuilder builder = new StringBuilder();
for (int i = 0; i < songlist.length; i++) {
builder.append(songlist[i]);
}
In that case you won't create new String object on each iteration
As "n" is not the size of the input, it can not really be O(n) or O(n^2).
If m is the length of all strings in songlist, then you are jumping over that string in steps of the size n. So the compelxity is related to m not to n. I did not calculate in big O etc. since a few decades ... however I would assume the complexity is O(m).