Algorithm - Lexicographically largest possible magical substring - java

I am working on this magical sub-string problem.
Magical binary strings are non-empty binary strings if the following two conditions are true:
The number of 0's is equal to the number of 1's.
For every prefix of the binary string, the number of 1's should not be less than the number of 0's.
I got stuck on how to proceed further in my Java program.
Here is my program:
static String findLargest(String str) {
String[] splits = str.split("");
Set<String> set = new LinkedHashSet<String>();
for (int i = 0; i < splits.length; i++) {
if (splits[i].equals("0")) {
continue;
}
int zeros = 0;
int ones = 0;
StringBuilder sb = new StringBuilder("");
for (int j = i; j < splits.length; j++) {
if (splits[j].equals("0")) {
zeros++;
} else {
ones++;
}
sb.append(splits[j]);
if (zeros == ones && ones >= zeros) {
set.add(sb.toString());
}
}
}
set.remove(str);
List<String> list = new ArrayList<String>(set);
System.out.println(list);
return null;
}
Using this program I am able to get the magical sub-strings for the given input String 11011000 as [10, 101100, 1100] in my list variable.
Now from here I am struggling how to remove the invalid entry of 101100 from my list and then use the elements 10, 1100 to swap from my input 11011000 to get the final result as 11100100
Also please guide me if there is any other alternate approach.

If your question is about only eliminating the unwanted "101100" from the result, here is the answer
import java.util.ArrayList;
import java.util.HashMap;
import java.lang.*;
import java.util.Set;
import java.util.*;
public class HelloWorld{
public static void main(String []args){
findLargest("11011000");
}
public static String findLargest(String str) {
String[] splits = str.split("");
Set<String> set = new LinkedHashSet<String>();
for (int i = 0; i < splits.length; i++) {
if (splits[i].equals("0")) {
continue;
}
int zeros = 0;
int ones = 0;
StringBuilder sb = new StringBuilder("");
for (int j = i; j < splits.length; j++) {
if (splits[j].equals("0")) {
zeros++;
} else {
ones++;
}
sb.append(splits[j]);
if (zeros == ones && ones >= zeros) {
set.add(sb.toString());
j = i +1; // RESET THE INDEX ELEMENT TO SKIP THE SUBSTRING FROM CONSIDERATION
break; // BREAK FROM THE LOOP
}
}
}
set.remove(str);
List<String> list = new ArrayList<String>(set);
System.out.println(list);
return null;
}
}

I can provide some points.
First, get all the magical substrings and store them as a pair of start and end index(l, r) in a list;
Second, sort the list based on index l;
Those who can be potentially swapped substring can get from the same index l. look at the example given "11011000"
the list will have (0,7),(1,2),(1,6),(3,6),(4,5)
obviously only potential swap is among (1,2)(1,6)
deal these substrings have same index l will help find potential swapping substrings, sort them to find the maximum order.

class Pair{
int start;
int end;
}
public List<Pair> findmagicalPairs(String binString){
List<Pair> magicPairs = new ArrayList<Pair>();
for(int start=0;start<binString.length()-1;start++){
int ones=0;
int zeros=0;
for(int i=start; i<binString.length();i++){
if(binString.charAt(i) == '1'){
ones++;
} else if(binString.charAt(i)=='0'){
zeros++;
}
if(ones == zeros){ //check if magical
Pair temp=new Pair();
temp.start=start;
temp.end =i;
magicPairs.add(temp);
}
}
}
return magicPairs;
}
public String largestMagical(String binString) {
// Write your code here
List<Pair> allPairs = findmagicalPairs(binString);
String largest=binString;
//check by swapping each pairs
for(int i=0;i<allPairs.size()-1;i++){
for(int j=i+1;j<allPairs.size()-1;j++){
if(allPairs.get(i).end+1 == allPairs.get(j).start){
//consecutive Pair so swap and see largest
int index = allPairs.get(j).start;
String swapped = binString.substring(0,allPairs.get(i).start)+binString.substring(allPairs.get(j).start,allPairs.get(j).end+1)+binString.substring(allPairs.get(i).start,allPairs.get(i).end+1)+binString.substring(allPairs.get(j).end+1);
largest = LargestString(largest, swapped);
} else {
//else ignore
}
}
}
return largest;
}
public String LargestString(String first, String second){
if(first.compareTo(second)>0){
return first;
} else {
return second;
}
}

JavaScript Code!
const largestMagical = (binString) => {
//console.log({ binString });
const len = binString.length;
const height = Array(len + 1).fill(0),
num = { 1: 1, 0: -1 },
marked = Array(len + 1).fill(false),
sameHeights = {};
let i,
j,
result = "";
for (i = 1; i <= len; ++i) {
height[i] = height[i - 1] + num[binString[i - 1]];
}
//console.log({ height });
for (i = 0; i <= len; ++i) {
if (marked[i]) continue;
marked[i] = true;
sameHeights[i] = [i];
for (j = i + 1; j <= len; ++j) {
if (height[j] < height[i]) break;
if (height[j] === height[i]) {
sameHeights[i].push(j);
marked[j] = true;
}
}
}
//console.log({ sameHeights });
for (let k in sameHeights) {
const leng = sameHeights[k].length;
let startId, midId, endId;
for (startId = 0; startId < leng - 2; ++startId) {
for (midId = startId + 1; midId < leng - 1; ++midId) {
for (endId = midId + 1; endId < leng; ++endId) {
const start = sameHeights[k][startId],
mid = sameHeights[k][midId],
end = sameHeights[k][endId];
//console.log({start, mid, end});
const swapped =
binString.substring(0, start) +
binString.substring(mid, end) +
binString.substring(start, mid) +
binString.substring(end, len);
//console.log({swapped});
if (swapped > result) result = swapped;
}
}
}
}
return result;
};
console.log(largestMagical("1010111000"));
console.log(largestMagical("11011000"));

Related

What does this syntax "search: " mean in java

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.

Even after using a global static array my values of the array are changing in java. How to overcome it?

In this code I am having some problem as I have marked using a loop which is printing some values. I am storing them in an array as mentioned and am trying to print the values in another function. But even after using the global array the value of the array is changing.
I am not able to figure out the problem. Please help me out.
import java.io.*;
import java.util.*;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
// Java program to print all permutations of a
// given string.
public class test3
{
static int[] val = new int[100] ; //array declaration as global
public static void main(String[] args)
{
System.out.println("An incremented value");
for(int i=2;i<=2;i++) {
String p="";
for(int j=0;j<=i;j++) {
for(int m=0;m<j;m++) {
p=p+"&";
}
for(int m=0;m<i-j;m++) {
p=p+"|";
}
printAllPermutations(p);
p="";
}
}
System.out.println();
for(int xy=0;xy<32;xy++)
System.out.print("["+xy+"]"+"="+val[xy]+" "); //trying to print the array
}
static void print(char[] temp) {
String a="";
System.out.println();
for (int i = 0; i < temp.length; i++)
{ System.out.print(temp[i]);
a=a+temp[i];}
System.out.print(" "+"opr:"+temp.length+" ");
final int N = temp.length+1;
/*===================CODE PROBLEM PART START=======================*/
for (int i = 0; i < (1 << N); i++) {
// System.out.println(zeroPad(Integer.toBinaryString(i), N));
String b=zeroPad(Integer.toBinaryString(i), N)+"";
// System.out.println("a: "+a+" b:"+b);
char[] arrayA = b.toCharArray();
char[] arrayB = a.toCharArray();
StringBuilder sb = new StringBuilder();
int ii = 0;
while( ii < arrayA.length && ii < arrayB.length){
sb.append(arrayA[ii]).append(arrayB[ii]);
++ii;
}
for(int j = ii; j < arrayA.length; ++j){
sb.append(arrayA[j]);
}
for(int j = ii; j < arrayB.length; ++j){
sb.append(arrayB[j]);
}
//System.out.println(sb.toString());
try {
ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine se = sem.getEngineByName("JavaScript");
String myExpression = sb.toString();
// System.out.print(se.eval(myExpression));
val[i]=(int)(se.eval(myExpression)); //inserting array value
System.out.print(val[i]); //NEED TO HAVE THESE VALUES IN THE 1-D ARRAY
// System.out.print(val[i]);
} catch (ScriptException e) {
System.out.println("Invalid Expression");
e.printStackTrace();}
}
/*===================CODE PROBLEM PART END========================*/
//
}
//unchangable = rest of the function
static int factorial(int n) {
int f = 1;
for (int i = 1; i <= n; i++)
f = f * i;
return f;
}
static int calculateTotal(char[] temp, int n) {
int f = factorial(n);
// Building HashMap to store frequencies of
// all characters.
HashMap<Character, Integer> hm =
new HashMap<Character, Integer>();
for (int i = 0; i < temp.length; i++) {
if (hm.containsKey(temp[i]))
hm.put(temp[i], hm.get(temp[i]) + 1);
else
hm.put(temp[i], 1);
}
// Traversing hashmap and finding duplicate elements.
for (Map.Entry e : hm.entrySet()) {
Integer x = (Integer)e.getValue();
if (x > 1) {
int temp5 = factorial(x);
f = f / temp5;
}
}
return f;
}
static void nextPermutation(char[] temp) {
// Start traversing from the end and
// find position 'i-1' of the first character
// which is greater than its successor.
int i;
for (i = temp.length - 1; i > 0; i--)
if (temp[i] > temp[i - 1])
break;
// Finding smallest character after 'i-1' and
// greater than temp[i-1]
int min = i;
int j, x = temp[i - 1];
for (j = i + 1; j < temp.length; j++)
if ((temp[j] < temp[min]) && (temp[j] > x))
min = j;
// Swapping the above found characters.
char temp_to_swap;
temp_to_swap = temp[i - 1];
temp[i - 1] = temp[min];
temp[min] = temp_to_swap;
// Sort all digits from position next to 'i-1'
// to end of the string.
Arrays.sort(temp, i, temp.length);
// Print the String
print(temp);
}
static void printAllPermutations(String s) {
// Sorting String
char temp[] = s.toCharArray();
Arrays.sort(temp);
// Print first permutation
print(temp);
// Finding the total permutations
int total = calculateTotal(temp, temp.length);
for (int i = 1; i < total; i++)
nextPermutation(temp);
}
static String zero(int L) {
return (L <= 0 ? "" : String.format("%0" + L + "d", 0));
}
static String zeroPad(String s, int L) {
return zero(L - s.length()) + s;
}
}
The output that I am getting is
An incremented value
|| opr:2 01111111 //WANT TO STORE THESE 32 VALUES IN 1 D ARRAY
&| opr:2 01010111 // AND PRINT THEM OUT
|& opr:2 00011111
&& opr:2 00000001
[0]=0 [1]=0 [2]=0 [3]=0 [4]=0 [5]=0 [6]=0 [7]=1 [8]=0 [9]=0 [10]=0 [11]=0 [12]=0 [13]=0 [14]=0 [15]=0 [16]=0 [17]=0 [18]=0 [19]=0 [20]=0 [21]=0 [22]=0 [23]=0 [24]=0 [25]=0 [26]=0 [27]=0 [28]=0 [29]=0 [30]=0 [31]=0
what I need to do is to store those 32 values in 1 D array for further operation but while doing it all the array values displays 0 only except [7]. I dont know whats going on here.
Reference types are not bound to local scopes, just because your array is static to the class it does not mean that changing the values in one function will not change the values in the actual array. The reference to your array as a parameter will be a copy, but the reference is still "pointing" on an actual object, which is not a copy bound to your local scope.
If you want to save two different states of the array, you will have to save them yourself.

Finding closest number to 0

I have an array of integers, and I need to find the one that's closest to zero (positive integers take priority over negative ones.)
Here is the code I have so far:
public class CloseToZero {
public static void main(String[] args) {
int[] data = {2,3,-2};
int curr = 0;
int near = data[0];
// find the element nearest to zero
for ( int i=0; i < data.length; i++ ){
curr = data[i] * data[i];
if ( curr <= (near * near) ) {
near = data[i];
}
}
System.out.println( near );
}
}
Currently I'm getting a result of -2 but I should be getting 2. What am I doing wrong?
This will do it in O(n) time:
int[] arr = {1,4,5,6,7,-1};
int closestIndex = 0;
int diff = Integer.MAX_VALUE;
for (int i = 0; i < arr.length; ++i) {
int abs = Math.abs(arr[i]);
if (abs < diff) {
closestIndex = i;
diff = abs;
} else if (abs == diff && arr[i] > 0 && arr[closestIndex] < 0) {
//same distance to zero but positive
closestIndex =i;
}
}
System.out.println(arr[closestIndex ]);
If you are using java8:
import static java.lang.Math.abs;
import static java.lang.Math.max;
public class CloseToZero {
public static void main(String[] args) {
int[] str = {2,3,-2};
Arrays.stream(str).filter(i -> i != 0)
.reduce((a, b) -> abs(a) < abs(b) ? a : (abs(a) == abs(b) ? max(a, b) : b))
.ifPresent(System.out::println);
}
}
Sort the array (add one line of code) so the last number you pick up will be positive if the same absolute value is selected for a positive and negative numbers with the same distance.
Source code:
import java.util.Arrays;
public class CloseToZero {
public static void main(String[] args) {
int[] data = {2,3,-2};
int curr = 0;
int near = data[0];
Arrays.sort(data); // add this
System.out.println(Arrays.toString(data));
// find the element nearest to zero
for ( int i=0; i < data.length; i++ ){
System.out.println("dist from " + data[i] + " = " + Math.abs(0 -data[i]));
curr = data[i] * data[i];
if ( curr <= (near * near) ) {
near = data[i];
}
}
System.out.println( near );
}
}
Just add zero to this list.
Then sort the list
Arrays.sort(data);
then grab the number before or after the zero and pick the minimum one greater than zero
Assumption is that the array data has at least 1 value.
int closestToZero = 0;
for ( int i = 1; i < data.length; i++ )
{
if ( Math.abs(data[i]) < Math.abs(data[closestToZero]) ) closestToZero = i;
}
The value in closestToZero is the index of the value closest to zero, not the value itself.
static int Solve(int N, int[] A){
int min = A[0];
for (int i=1; i<N ; i++){
min = min > Math.abs(0- A[i]) ? Math.abs(0- A[i]) : Math.abs(min);
}
return min;
}
As you multiply data[i] with data[i], a value negative and a value positive will have the same impact.
For example, in your example: 2 and -2 will be 4. So, your code is not able to sort as you need.
So, here, it takes -2 as the near value since it has the same "weight" as 2.
I have same answer with different method,Using Collections and abs , we can solved.
static int Solve(int N, int[] A){
List<Integer> mInt=new ArrayList<>();
for ( int i=0; i < A.length; i++ ){
mInt.add(Math.abs(0 -A[i]));
}
return Collections.min(mInt);
}
That all,As simple as that
This is a very easy to read O(n) solution for this problem.
int bigestNegative = Integer.MIN_VALUE;
int smalestpositive = Integer.MAX_VALUE;
int result = 0;
for (int i = 0; i < n; i++) {
//if the zero should be considered as result as well
if ( temperatures[i] == 0 ) {
result = 0;
break;
}
if ( temperatures[i] > 0 && temperatures[i] < smalestpositive ) {
smalestpositive = temperatures[i];
}
if ( temperatures[i] < 0 && temperatures[i] > bigestNegative ) {
bigestNegative = temperatures[i];
}
}
if( (Math.abs(bigestNegative)) < (Math.abs(smalestpositive)) && bigestNegative != Integer.MIN_VALUE)
result = bigestNegative;
else
result = smalestpositive;
System.out.println( result );
First convert the int array into stream. Then sort it with default sorting order. Then filter greater than zero & peek the first element & print it.
Do it in declarative style which describes 'what to do', not 'how to do'. This style is more readable.
int[] data = {2,3,-2};
IntStream.of(data)
.filter(i -> i>0)
.sorted()
.limit(1)
.forEach(System.out::println);
using Set Collection and abs methode to avoid complex algo
public static void main(String[] args) {
int [] temperature={0};
***// will erase double values and order them from small to big***
Set<Integer> s= new HashSet<Integer>();
if (temperature.length!=0) {
for(int i=0; i<temperature.length; i++) {
***// push the abs value to the set***
s.add(Math.abs(temperature[i]));
}
// remove a zero if exists in the set
while(s.contains(0)) {
s.remove(0);
}
***// get first (smallest) element of the set : by default it is sorted***
if (s.size()!=0) {
Iterator iter = s.iterator();
System.out.println(iter.next());
}
else System.out.println(0);
}
else System.out.println(0);
}
static int nearToZero(int[] A){
Arrays.sort(A);
int ans = 0;
List<Integer> list = Arrays.stream(A).boxed().collect(Collectors.toList());
List<Integer> toRemove = new ArrayList<>();
List<Integer> newList = new ArrayList<>();
for(int num: list){
if(newList.contains(num)) toRemove.add(num);
else newList.add(num);
}
list.removeAll(toRemove);
for(int num : list){
if(num == 0 ) return 0;
if(ans == 0 )ans = num;
if(num < 0 && ans < num) ans = num;
if(num < ans) ans = num;
if(num > 0 && Math.abs(ans) >= num) ans = num;
}
return ans;
}
here is a method that gives you the nearest to zero.
use case 1 : {1,3,-2} ==> return 1 : use the Math.abs() for comparison and get the least.
use case 2 : {2,3,-2} ==> return 2 : use the Math.abs() for comparison and get the Math.abs(least)
use case 3 : {-2,3,-2} ==> return -2: use the Math.abs() for comparison and get the least.
public static double getClosestToZero(double[] liste) {
// if the list is empty return 0
if (liste.length != 0) {
double near = liste[0];
for (int i = 0; i < liste.length; i++) {
// here we are using Math.abs to manage the negative and
// positive number
if (Math.abs(liste[i]) <= Math.abs(near)) {
// manage the case when we have two equal neagative numbers
if (liste[i] == -near) {
near = Math.abs(liste[i]);
} else {
near = liste[i];
}
}
}
return near;
} else {
return 0;
}
}
You can do like this:
String res = "";
Arrays.sort(arr);
int num = arr[0];
int ClosestValue = 0;
for (int i = 0; i < arr.length; i++)
{
//for negatives
if (arr[i] < ClosestValue && arr[i] > num)
num = arr[i];
//for positives
if (arr[i] > ClosestValue && num < ClosestValue)
num = arr[i];
}
res = num;
System.out.println(res);
First of all you need to store all your numbers into an array. After that sort the array --> that's the trick who will make you don't use Math.abs(). Now is time to make a loop that iterates through the array. Knowing that array is sorted is important that you start to make first an IF statement for negatives numbers then for the positives (in this way if you will have two values closest to zero, let suppose -1 and 1 --> will print the positive one).
Hope this will help you.
The easiest way to deal with this is split the array into positive and negative sort and push the first two items from both the arrays into another array. Have fun!
function closeToZeroTwo(arr){
let arrNeg = arr.filter(x => x < 0).sort();
let arrPos = arr.filter(x => x > 0).sort();
let retArr = [];
retArr.push(arrNeg[0], arrPos[0]);
console.log(retArr)
}
Easiest way to just sort that array in ascending order suppose input is like :
int[] array = {10,-5,5,2,7,-4,28,65,95,85,12,45};
then after sorting it will gives output like:
{-5,-4,2,5,7,10,12,28,45,65,85,95,}
and for positive integer number, the Closest Positive number is: 2
Logic :
public class Closest {
public static int getClosestToZero(int[] a) {
int temp=0;
//following for is used for sorting an array in ascending nubmer
for (int i = 0; i < a.length-1; i++) {
for (int j = 0; j < a.length-i-1; j++) {
if (a[j]>a[j+1]) {
temp = a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
//to check sorted array with negative & positive values
System.out.print("{");
for(int number:a)
System.out.print(number + ",");
System.out.print("}\n");
//logic for check closest positive and Integer
for (int i = 0; i < a.length; i++) {
if (a[i]<0 && a[i+1]>0) {
temp = a[i+1];
}
}
return temp;
}
public static void main(String[] args) {
int[] array = {10,-5,5,2,7,-4,28,65,95,85,12,45};
int closets =getClosestToZero(array);
System.out.println("The Closest Positive number is : "+closets);
}
}
static void closestToZero(){
int[] arr = {45,-4,-12,-2,7,4};
int max = Integer.MAX_VALUE;
int closest = 0;
for (int i = 0; i < arr.length; i++){
int value = arr[i];
int abs = Math.abs(value);
if (abs < max){
max = abs;
closest = value;
}else if (abs == max){
if (value > closest){
closest = value;
}
}
}
Return a positive integer if two absolute values are the same.
package solution;
import java.util.Scanner;
public class Solution {
public static void trier(int tab[]) {
int tmp = 0;
for(int i = 0; i < (tab.length - 1); i++) {
for(int j = (i+1); j< tab.length; j++) {
if(tab[i] > tab[j]) {
tmp = tab[i];
tab[i] = tab[j];
tab[j] = tmp;
}
}
}
int prochePositif = TableauPositif(tab);
int procheNegatif = TableauNegatif(tab);
System.out.println(distanceDeZero(procheNegatif,prochePositif));
}
public static int TableauNegatif(int tab[]) {
int taille = TailleNegatif(tab);
int tabNegatif[] = new int[taille];
for(int i = 0; i< tabNegatif.length; i++) {
tabNegatif[i] = tab[i];
}
int max = tabNegatif[0];
for(int i = 0; i <tabNegatif.length; i++) {
if(max < tabNegatif[i])
max = tabNegatif[i];
}
return max;
}
public static int TableauPositif(int tab[]) {
int taille = TailleNegatif(tab);
if(tab[taille] ==0)
taille+=1;
int taillepositif = TaillePositif(tab);
int tabPositif[] = new int[taillepositif];
for(int i = 0; i < tabPositif.length; i++) {
tabPositif[i] = tab[i + taille];
}
int min = tabPositif[0];
for(int i = 0; i< tabPositif.length; i++) {
if(min > tabPositif[i])
min = tabPositif[i];
}
return min;
}
public static int TailleNegatif(int tab[]) {
int cpt = 0;
for(int i = 0; i < tab.length; i++) {
if(tab[i] < 0) {
cpt +=1;
}
}
return cpt;
}
public static int TaillePositif(int tab[]) {
int cpt = 0;
for(int i = 0; i < tab.length; i++) {
if(tab[i] > 0) {
cpt +=1;
}
}
return cpt;
}
public static int distanceDeZero(int v1, int v2) {
int absv1 = v1 * (-1);
if(absv1 < v2)
return v1;
else if(absv1 > v2)
return v2;
else
return v2;
}
public static void main(String[] args) {
int t[] = {6,5,8,8,-2,-5,0,-3,-5,9,7,4};
Solution.trier(t);
}
}
To maintain O(n) time complexity and getting the desired results we have to add another variable called 'num' and assign to it 'near' before changing it's value. And finally make necessary checks. The improvements in the code are are:
public class CloseToZero {
public static void main(String[] args) {
int[] data = {2,3,-2};
int curr = 0;
int near = data[0];
int num=near;
// find the element nearest to zero
for ( int i=0; i < data.length; i++ ){
curr = data[i] * data[i];
if ( curr <= (near * near) ) {
num=near;
near = data[i];
}
}
if(near<0 && near*(-1)==num)
near=num;
System.out.println( near );
}
}
We have to find the Closest number to zero.
The given array can have negative values also.
So the easiest approach would append the '0' in the given array and sort it and return the element next to '0'
append the 0
Sort the Array
Return the element next to 0.
`
N = int(input())
arr = list(map(int, input().split()))
arr.append(0)
arr.sort()
zeroIndex = arr.index(0)
print(arr[zeroIndex + 1])
--> If this solution leaves corner cases please let me know also.
`
if you don't wanna use the inbuilt library function use the below code (just an and condition with your existing code)-
public class CloseToZero {
public static void main(String[] args) {
int[] data = {2,3,-2,-1,1};
int curr = 0;
int near = data[0];
// find the element nearest to zero
for ( int i=0; i < data.length; i++ ){
curr = data[i] * data[i];
if ( curr <= (near * near) && !((curr - (near * near) == 0) && data[i] < 0)) {
near = data[i];
}
}
System.out.println( near );
}
}
!((curr - (near * near) == 0) && data[i] < 0) : skip asignment if if near and curr is just opposit in sign and the curr is negative
public static int find(int[] ints) {
if (ints==null) return 0;
int min= ints[0]; //a random value initialisation
for (int k=0;k<ints.length;k++) {
// if a positive value is matched it is prioritized
if (ints[k]==Math.abs(min) || Math.abs(ints[k])<Math.abs(min))
min=ints[k];
}
return min;
}
public int check() {
int target = 0;
int[] myArray = { 40, 20, 100, 30, -1, 70, -10, 500 };
int result = myArray[0];
for (int i = 0; i < myArray.length; i++) {
if (myArray[i] == target) {
result = myArray[i];
return result;
}
if (myArray[i] > 0 && result >= (myArray[i] - target)) {
result = myArray[i];
}
}
return result;
}
I have added a check for the positive number itself.
Please share your views folks!!
public class ClosesttoZero {
static int closZero(int[] ints) {
int result=ints[0];
for(int i=1;i<ints.length;i++) {
if(Math.abs(result)>=Math.abs(ints[i])) {
result=Math.abs(ints[i]);
}
}
return result;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] ints= {1,1,5,8,4,-9,0,6,7,1};
int result=ClosesttoZero.closZero(ints);
System.out.println(result);
}
}
It can be done simply by making all numbers positive using absolute value then sort the Array:
int[] arr = {9, 1, 4, 5, 6, 7, -1, -2};
for (int i = 0; i < arr.length; ++i)
{
arr[i] = Math.abs(arr[i]);
}
Arrays.sort(arr);
System.out.println("Closest value to 0 = " + arr[0]);
import java.math.*;
class Solution {
static double closestToZero(double[] ts) {
if (ts.length == 0)
return 0;
double closestToZero = ts[0];
double absClosest = Math.abs(closestToZero);
for (int i = 0; i < ts.length; i++) {
double absValue = Math.abs(ts[i]);
if (absValue < absClosest || absValue == absClosest && ts[i] > 0) {
closestToZero = ts[i];
absClosest = absValue;
}
}
return closestToZero;
}
}
//My solution priorizing positive numbers contraint
int closestToZero = Integer.MAX_VALUE;//or we
for(int i = 0 ; i < arrayInt.length; i++) {
if (Math.abs(arrayInt[i]) < closestToZero
|| Math.abs(closestToZero) == Math.abs(arrayInt[i]) && arrayInt[i] > 0 ) {
closestToZero = arrayInt[i];
}
}

How to find the longest substring containing two unique repeating characters

The task is to find the longest substring in a given string that is composed of any two unique repeating characters
Ex. in an input string "aabadefghaabbaagad", the longest such string is "aabbaa"
I came up with the following solution but wanted to see if there is a more efficient way to do the same
import java.util.*;
public class SubString {
public static void main(String[] args) {
//String inStr="defghgadaaaaabaababbbbbbd";
String inStr="aabadefghaabbaagad";
//String inStr="aaaaaaaaaaaaaaaaaaaa";
System.out.println("Input string is "+inStr);
StringBuilder sb = new StringBuilder(inStr.length());
String subStr="";
String interStr="";
String maxStr="";
int start=0,length=0, maxStart=0, maxlength=0, temp=0;
while(start+2<inStr.length())
{ int i=0;
temp=start;
char x = inStr.charAt(start);
char y = inStr.charAt(start+1);
sb.append(x);
sb.append(y);
while( (x==y) && (start+2<inStr.length()) )
{ start++;
y = inStr.charAt(start+1);
sb.append(y);
}
subStr=inStr.substring(start+2);
while(i<subStr.length())
{ if(subStr.charAt(i)==x || subStr.charAt(i)==y )
{ sb.append(subStr.charAt(i));
i++;
}
else
break;
}
interStr= sb.toString();
System.out.println("Intermediate string "+ interStr);
length=interStr.length();
if(maxlength<length)
{ maxlength=length;
length=0;
maxStr = new String(interStr);
maxStart=temp;
}
start++;
sb.setLength(0);
}
System.out.println("");
System.out.println("Longest string is "+maxStr.length()+" chars long "+maxStr);
}
}
Here's a hint that might guide you towards a linear-time algorithm (I assume that this is homework, so I won't give the entire solution): At the point where you have found a character that is neither equal to x nor to y, it is not necessary to go all the way back to start + 1 and restart the search. Let's take the string aabaaddaa. At the point where you have seen aabaa and the next character is d, there is no point in restarting the search at index 1 or 2, because in those cases, you'll only get abaa or baa before hitting d again. As a matter of fact, you can move start directly to index 3 (the first index of the last group of as), and since you already know that there is a contiguous sequene of as up to d, you can move i to index 5 and continue.
Edit: Pseudocode below.
// Find the first letter that is not equal to the first one,
// or return the entire string if it consists of one type of characters
int start = 0;
int i = 1;
while (i < str.length() && str[i] == str[start])
i++;
if (i == str.length())
return str;
// The main algorithm
char[2] chars = {str[start], str[i]};
int lastGroupStart = 0;
while (i < str.length()) {
if (str[i] == chars[0] || str[i] == chars[1]) {
if (str[i] != str[i - 1])
lastGroupStart = i;
}
else {
//TODO: str.substring(start, i) is a locally maximal string;
// compare it to the longest one so far
start = lastGroupStart;
lastGroupStart = i;
chars[0] = str[start];
chars[1] = str[lastGroupStart];
}
i++;
}
//TODO: After the loop, str.substring(start, str.length())
// is also a potential solution.
Same question to me, I wrote this code
public int getLargest(char [] s){
if(s.length<1) return s.length;
char c1 = s[0],c2=' ';
int start = 1,l=1, max=1;
int i = 1;
while(s[start]==c1){
l++;
start++;
if(start==s.length) return start;
}
c2 = s[start];
l++;
for(i = l; i<s.length;i++){
if(s[i]==c1 || s[i]==c2){
if(s[i]!=s[i-1])
start = i;
l++;
}
else {
l = i-start+1;
c1 = s[start];
c2 = s[i];
start = i;
}
max = Math.max(l, max);
}
return max;
}
so the way I think of this is to solve it in 2 steps
scan the entire string to find continuous streams of the same letter
loop the extracted segments and condense them until u get a gap.
This way you can also modify the logic to scan for longest sub-string of any length not just 2.
class Program
{
static void Main(string[] args)
{
//.
string input = "aabbccdddxxxxxxxxxxxxxxxxx";
int max_chars = 2;
//.
int flip = 0;
var scanned = new List<string>();
while (flip > -1)
{
scanned.Add(Scan(input, flip, ref flip));
}
string found = string.Empty;
for(int i=0;i<scanned.Count;i++)
{
var s = Condense(scanned, i, max_chars);
if (s.Length > found.Length)
{
found = s;
}
}
System.Console.WriteLine("Found:" + found);
System.Console.ReadLine();
}
/// <summary>
///
/// </summary>
/// <param name="s"></param>
/// <param name="start"></param>
/// <returns></returns>
private static string Scan(string s, int start, ref int flip)
{
StringBuilder sb = new StringBuilder();
flip = -1;
sb.Append(s[start]);
for (int i = start+1; i < s.Length; i++)
{
if (s[i] == s[i - 1]) { sb.Append(s[i]); continue; } else { flip=i; break;}
}
return sb.ToString();
}
/// <summary>
///
/// </summary>
/// <param name="list"></param>
/// <param name="start"></param>
/// <param name="repeat"></param>
/// <param name="flip"></param>
/// <returns></returns>
private static string Condense(List<string> list, int start, int repeat)
{
StringBuilder sb = new StringBuilder();
List<char> domain = new List<char>(){list[start][0]};
for (int i = start; i < list.Count; i++)
{
bool gap = false;
for (int j = 0; j < domain.Count; j++)
{
if (list[i][0] == domain[j])
{
sb.Append(list[i]);
break;
}
else if (domain.Count < repeat)
{
domain.Add(list[i][0]);
sb.Append(list[i]);
break;
}
else
{
gap=true;
break;
}
}
if (gap) { break;}
}
return sb.ToString();
}
}
A general solution: Longest Substring Which Contains K Unique Characters.
int longestKCharSubstring(string s, int k) {
int i, max_len = 0, start = 0;
// either unique char & its last pos
unordered_map<char, int> ht;
for (i = 0; i < s.size(); i++) {
if (ht.size() < k || ht.find(s[i]) != ht.end()) {
ht[s[i]] = i;
} else {
// (k + 1)-th char
max_len = max(max_len, i - start);
// start points to the next of the earliest char
char earliest_char;
int earliest_char_pos = INT_MAX;
for (auto key : ht)
if (key.second < earliest_char_pos)
earliest_char = key.first;
start = ht[earliest_char] + 1;
// replace earliest_char
ht.erase(earliest_char);
ht[s[i]] = i;
}
}
// special case: e.g., "aaaa" or "aaabb" when k = 2
if (k == ht.size())
max_len = max(max_len, i - start);
return max_len;
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap; import java.util.Iterator; import java.util.List;
import java.util.Map;
public class PrintLLargestSubString {
public static void main(String[] args){ String string =
"abcdefghijklmnopqrstuvbcdefghijklmnopbcsdcelfabcdefghi";
List<Integer> list = new ArrayList<Integer> (); List<Integer>
keyList = new ArrayList<Integer> (); List<Integer> Indexlist = new
ArrayList<Integer> (); List<Integer> DifferenceList = new
ArrayList<Integer> (); Map<Integer, Integer> map = new
HashMap<Integer, Integer>(); int index = 0; int len = 1; int
j=1; Indexlist.add(0); for(int i = 0; i< string.length() ;i++) {
if(j< string.length()){
if(string.charAt(i) < string.charAt(j)){
len++;
list.add(len);
} else{
index= i+1;
Indexlist.add(index); // System.out.println("\nindex" + index);
len=1;
} } j++; } // System.out.println("\nlist" +list); System.out.println("index List" +Indexlist); // int n =
Collections.max(list); // int ind = Collections.max(Indexlist);
// System.out.println("Max number in IndexList " +n);
// System.out.println("Index Max is " +ind);
//Finding max difference in a list of elements for(int diff = 0;
diff< Indexlist.size()-1;diff++){ int difference =
Indexlist.get(diff+1)-Indexlist.get(diff);
map.put(Indexlist.get(diff), difference);
DifferenceList.add(difference); }
System.out.println("Difference between indexes" +DifferenceList); // Iterator<Integer> keySetIterator = map.keySet().iterator(); // while(keySetIterator.hasNext()){
// Integer key = keySetIterator.next();
// System.out.println("index: " + key + "\tDifference "
+map.get(key)); // // } // System.out.println("Diffferenece List" +DifferenceList); int maxdiff = Collections.max(DifferenceList); System.out.println("Max diff is " + maxdiff); ////// Integer
value = maxdiff; int key = 0; keyList.addAll(map.keySet());
Collections.sort(keyList); System.out.println("List of al keys"
+keyList); // System.out.println(map.entrySet()); for(Map.Entry entry: map.entrySet()){ if(value.equals(entry.getValue())){
key = (int) entry.getKey(); } } System.out.println("Key value of max difference starting element is " + key);
//Iterating key list and finding next key value int next = 0 ;
int KeyIndex = 0; int b; for(b= 0; b<keyList.size(); b++) {
if(keyList.get(b)==key){
KeyIndex = b; } } System.out.println("index of key\t" +KeyIndex); int nextIndex = KeyIndex+1; System.out.println("next Index = " +nextIndex); next = keyList.get(nextIndex);
System.out.println("next Index value is = " +next);
for( int z = KeyIndex; z < next ; z++) {
System.out.print(string.charAt(z)); } }
}
The problem can be solved in O(n). Idea is to maintain a window and add elements to the window till it contains less or equal 2, update our result if required while doing so. If unique elements exceeds than required in window, start removing the elements from left side.
#code
from collections import defaultdict
def solution(s, k):
length = len(set(list(s)))
count_dict = defaultdict(int)
if length < k:
return "-1"
res = []
final = []
maxi = -1
for i in range(0, len(s)):
res.append(s[i])
if len(set(res)) <= k:
if len(res) >= maxi and len(set(res)) <= k :
maxi = len(res)
final = res[:]
count_dict[maxi] += 1
else:
while len(set(res)) != k:
res = res[1:]
if maxi <= len(res) and len(set(res)) <= k:
maxi = len(res)
final = res[:]
count_dict[maxi] += 1
return len(final)
print(solution(s, k))
The idea here is to add occurrence of each character to a hashmap, and when the hasmap size increases more than k, remove the unwanted character.
private static int getMaxLength(String str, int k) {
if (str.length() == k)
return k;
var hm = new HashMap<Character, Integer>();
int maxLength = 0;
int startCounter = 0;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (hm.get(c) != null) {
hm.put(c, hm.get(c) + 1);
} else {
hm.put(c, 1);
}
//atmost K different characters
if (hm.size() > k) {
maxLength = Math.max(maxLength, i - startCounter);
while (hm.size() > k) {
char t = str.charAt(startCounter);
int count = hm.get(t);
if (count > 1) {
hm.put(t, count - 1);
} else {
hm.remove(t);
}
startCounter++;
}
}
}
return maxLength;
}

Big O for this code

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).

Categories