Find the maximum product of two non overlapping palindromic subsequences - java

I am trying to find the maximum product of two non overlapping palindromic sub-sequences of string s that we'll refer to as a and b. I came up with below code but it's not giving correct output:
public static int max(String s) {
int[][] dp = new int[s.length()][s.length()];
for (int i = s.length() - 1; i >= 0; i--) {
dp[i][i] = 1;
for (int j = i+1; j < s.length(); j++) {
if (s.charAt(i) == s.charAt(j)) {
dp[i][j] = dp[i+1][j-1] + 2;
} else {
dp[i][j] = Math.max(dp[i+1][j], dp[i][j-1]);
}
}
}
return dp[0][s.length()-1];
}
For input string "acdapmpomp", we can choose a = "aca" and b ="pmpmp" to get a maximal product of score 3 * 5 = 15. But my program gives output as 5.

Firstly you should traverse the dp table to find out the length of longest palindromic subsequences using bottom up approach, then you can calculate the max product by multiplying dp[i][j] with dp[j+1][n-1] : Given below is the code in C++;
int longestPalindromicSubsequenceProduct(string x){
int n = x.size();
vector<vector<int>> dp(n,vector<int>(n,0));
for(int i=0;i<n;i++){
dp[i][i] = 1;
}
for(int k=1;k<n;k++){
for(int i=0;i<n-k;i++){
int j = i + k;
if(x[i]==x[j]){
dp[i][j] = 2 + dp[i+1][j-1];
} else{
dp[i][j] = max(dp[i][j-1],dp[i+1][j]);
}
}
}
int maxProd = 0;
for(int i=0;i<n;i++){
for(int j=0;j<n-1;j++){
maxProd = max(maxProd,dp[i][j]*dp[j+1][n-1]);
}
}
return maxProd;
}

int multiplyPalindrome(string s) {
int n=s.size(),m=0;
vector<vector<int>> dp(n, vector<int> (n));
for(int i=0;i<n;i++) dp[i][i]=1;
for (int cl=2; cl<=n; cl++) {
for (int i=0; i<n-cl+1; i++){
int j = i+cl-1;
if (s[i] == s[j] && cl == 2) dp[i][j] = 2;
else if (s[i] == s[j]) dp[i][j] = dp[i+1][j-1] + 2;
else dp[i][j] = max(dp[i][j-1], dp[i+1][j]);
}
}
for(int i=0;i<n-1;i++){
m = max( m, dp[0][i]*dp[i+1][n-1] );
}
return m;
}

int palSize(string &s, int mask) {
int p1 = 0, p2 = s.size(), res = 0;
while (p1 <= p2) {
if ((mask & (1 << p1)) == 0)
++p1;
else if ((mask & (1 << p2)) == 0)
--p2;
else if (s[p1] != s[p2])
return 0;
else
res += 1 + (p1++ != p2--);
}
return res;
}
int maxProduct(string s) {
int mask[4096] = {}, res = 0;
for (int m = 1; m < (1 << s.size()); ++m)
mask[m] = palSize(s, m);
for (int m1 = 1; m1 < (1 << s.size()); ++m1)
if (mask[m1])
for (int m2 = 1; m2 < (1 << s.size()); ++m2)
if ((m1 & m2) == 0)
res = max(res, mask[m1] * mask[m2]);
return res;
}

You can loop through all non-overlapping palindromic subsequences and return the maximum value.
public int longestPalindromicSubsequenceProduct(String str) {
int maxProduct = 0;
for (int k = 0; k < str.length(); k++) {
String left = str.substring(0, k);
String right = str.substring(k);
int currProduct = longestPalindromicSubsequence(left) * longestPalindromicSubsequence(right);
maxProduct = Math.max(maxProduct, currProduct);
}
return maxProduct;
}
private int longestPalindromicSubsequence(String org) {
String rev = new StringBuilder(org).reverse().toString();
return longestCommonSubsequence(org, rev);
}
private int longestCommonSubsequence(String str1, String str2) {
int rows = str1.length();
int cols = str2.length();
int[][] dp = new int[rows + 1][cols + 1];
for (int r = 1; r <= rows; r++) {
for (int c = 1; c <= cols; c++) {
if (str1.charAt(r - 1) == str2.charAt(c - 1)) dp[r][c] = 1 + dp[r - 1][c - 1];
else dp[r][c] = Math.max(dp[r - 1][c], dp[r][c - 1]);
}
}
return dp[rows][cols];
}

Your algorithm returns the maximum length of a palyndrome, not the maximum of the product of two lengths.
UPDATE
Here's a possible solution:
public static int max(String s) {
int max = 0;
for (int i = 1; i < s.length()-1; ++i) {
String p1 = bestPalyndrome(s, 0, i);
String p2 = bestPalyndrome(s, i, s.length());
int prod = p1.length()*p2.length();
if (prod > max) {
System.out.println(p1 + " " + p2 + " -> " + prod);
max = prod;
}
}
return max;
}
private static String bestPalyndrome(String s, int start, int end) {
if (start >= end) {
return "";
} else if (end-start == 1) {
return s.substring(start, end);
} else if (s.charAt(start) == s.charAt(end-1)) {
return s.charAt(start) + bestPalyndrome(s, start+1, end-1)
+ s.charAt(end-1);
} else {
String s1 = bestPalyndrome(s, start, end-1);
String s2 = bestPalyndrome(s, start+1, end);
return s2.length() > s1.length() ? s2 : s1;
}
}

Related

Count the minimum number of jumps required for a frog to get to the other side of a river

I work with a Codility problem provided below,
The Fibonacci sequence is defined using the following recursive formula:
F(0) = 0
F(1) = 1
F(M) = F(M - 1) + F(M - 2) if M >= 2
A small frog wants to get to the other side of a river. The frog is initially located at one bank of the river (position −1) and wants to get to the other bank (position N). The frog can jump over any distance F(K), where F(K) is the K-th Fibonacci number. Luckily, there are many leaves on the river, and the frog can jump between the leaves, but only in the direction of the bank at position N.
The leaves on the river are represented in an array A consisting of N integers. Consecutive elements of array A represent consecutive positions from 0 to N − 1 on the river. Array A contains only 0s and/or 1s:
0 represents a position without a leaf;
1 represents a position containing a leaf.
The goal is to count the minimum number of jumps in which the frog can get to the other side of the river (from position −1 to position N). The frog can jump between positions −1 and N (the banks of the river) and every position containing a leaf.
For example, consider array A such that:
A[0] = 0
A[1] = 0
A[2] = 0
A[3] = 1
A[4] = 1
A[5] = 0
A[6] = 1
A[7] = 0
A[8] = 0
A[9] = 0
A[10] = 0
The frog can make three jumps of length F(5) = 5, F(3) = 2 and F(5) = 5.
Write a function:
class Solution { public int solution(int[] A); }
that, given an array A consisting of N integers, returns the minimum number of jumps by which the frog can get to the other side of the river. If the frog cannot reach the other side of the river, the function should return −1.
For example, given:
A[0] = 0
A[1] = 0
A[2] = 0
A[3] = 1
A[4] = 1
A[5] = 0
A[6] = 1
A[7] = 0
A[8] = 0
A[9] = 0
A[10] = 0
the function should return 3, as explained above.
Assume that:
N is an integer within the range [0..100,000];
each element of array A is an integer that can have one of the following values: 0, 1.
Complexity:
expected worst-case time complexity is O(N*log(N));
expected worst-case space complexity is O(N) (not counting the storage required for input arguments).
I wrote the following solution,
class Solution {
private class Jump {
int position;
int number;
public int getPosition() {
return position;
}
public int getNumber() {
return number;
}
public Jump(int pos, int number) {
this.position = pos;
this.number = number;
}
}
public int solution(int[] A) {
int N = A.length;
List<Integer> fibs = getFibonacciNumbers(N + 1);
Stack<Jump> jumps = new Stack<>();
jumps.push(new Jump(-1, 0));
boolean[] visited = new boolean[N];
while (!jumps.isEmpty()) {
Jump jump = jumps.pop();
int position = jump.getPosition();
int number = jump.getNumber();
for (int fib : fibs) {
if (position + fib > N) {
break;
} else if (position + fib == N) {
return number + 1;
} else if (!visited[position + fib] && A[position + fib] == 1) {
visited[position + fib] = true;
jumps.add(new Jump(position + fib, number + 1));
}
}
}
return -1;
}
private List<Integer> getFibonacciNumbers(int N) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 2; i++) {
list.add(i);
}
int i = 2;
while (list.get(list.size() - 1) <= N) {
list.add(i, (list.get(i - 1) + list.get(i - 2)));
i++;
}
for (i = 0; i < 2; i++) {
list.remove(i);
}
return list;
}
public static void main(String[] args) {
int[] A = new int[11];
A[0] = 0;
A[1] = 0;
A[2] = 0;
A[3] = 1;
A[4] = 1;
A[5] = 0;
A[6] = 1;
A[7] = 0;
A[8] = 0;
A[9] = 0;
A[10] = 0;
System.out.println(solution(A));
}
}
However, while the correctness seems good, the performance is not high enough. Is there a bug in the code and how do I improve the performance?
Got 100% with simple BFS:
public class Jump {
int pos;
int move;
public Jump(int pos, int move) {
this.pos = pos;
this.move = move;
}
}
public int solution(int[] A) {
int n = A.length;
List < Integer > fibs = fibArray(n + 1);
Queue < Jump > positions = new LinkedList < Jump > ();
boolean[] visited = new boolean[n + 1];
if (A.length <= 2)
return 1;
for (int i = 0; i < fibs.size(); i++) {
int initPos = fibs.get(i) - 1;
if (A[initPos] == 0)
continue;
positions.add(new Jump(initPos, 1));
visited[initPos] = true;
}
while (!positions.isEmpty()) {
Jump jump = positions.remove();
for (int j = fibs.size() - 1; j >= 0; j--) {
int nextPos = jump.pos + fibs.get(j);
if (nextPos == n)
return jump.move + 1;
else if (nextPos < n && A[nextPos] == 1 && !visited[nextPos]) {
positions.add(new Jump(nextPos, jump.move + 1));
visited[nextPos] = true;
}
}
}
return -1;
}
private List < Integer > fibArray(int n) {
List < Integer > fibs = new ArrayList < > ();
fibs.add(1);
fibs.add(2);
while (fibs.get(fibs.size() - 1) + fibs.get(fibs.size() - 2) <= n) {
fibs.add(fibs.get(fibs.size() - 1) + fibs.get(fibs.size() - 2));
}
return fibs;
}
You can apply knapsack algorithms to solve this problem.
In my solution I precomputed fibonacci numbers. And applied knapsack algorithm to solve it. It contains duplicate code, did not have much time to refactor it. Online ide with the same code is in repl
import java.util.*;
class Main {
public static int solution(int[] A) {
int N = A.length;
int inf=1000000;
int[] fibs={1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025};
int[] moves = new int[N+1];
for(int i=0; i<=N; i++){
moves[i]=inf;
}
for(int i=0; i<fibs.length; i++){
if(fibs[i]-1<N && A[fibs[i]-1]==1){
moves[ fibs[i]-1 ] = 1;
}
if(fibs[i]-1==N){
moves[N] = 1;
}
}
for(int i=0; i<N; i++){
if(A[i]==1)
for(int j=0; j<fibs.length; j++){
if(i-fibs[j]>=0 && moves[i-fibs[j]]!=inf && moves[i]>moves[i-fibs[j]]+1){
moves[i]=moves[i-fibs[j]]+1;
}
}
System.out.println(i + " => " + moves[i]);
}
for(int i=N; i<=N; i++){
for(int j=0; j<fibs.length; j++){
if(i-fibs[j]>=0 && moves[i-fibs[j]]!=inf && moves[i]>moves[i-fibs[j]]+1){
moves[i]=moves[i-fibs[j]]+1;
}
}
System.out.println(i + " => " + moves[i]);
}
if(moves[N]==inf) return -1;
return moves[N];
}
public static void main(String[] args) {
int[] A = new int[4];
A[0] = 0;
A[1] = 0;
A[2] = 0;
A[3] = 0;
System.out.println(solution(A));
}
}
Javascript 100%
function solution(A) {
function fibonacciUntilNumber(n) {
const fib = [0,1];
while (true) {
let newFib = fib[fib.length - 1] + fib[fib.length - 2];
if (newFib > n) {
break;
}
fib.push(newFib);
}
return fib.slice(2);
}
A.push(1);
const fibSet = fibonacciUntilNumber(A.length);
if (fibSet.includes(A.length)) return 1;
const reachable = Array.from({length: A.length}, () => -1);
fibSet.forEach(jump => {
if (A[jump - 1] === 1) {
reachable[jump - 1] = 1;
}
})
for (let index = 0; index < A.length; index++) {
if (A[index] === 0 || reachable[index] > 0) {
continue;
}
let minValue = 100005;
for (let jump of fibSet) {
let previousIndex = index - jump;
if (previousIndex < 0) {
break;
}
if (reachable[previousIndex] > 0 && minValue > reachable[previousIndex]) {
minValue = reachable[previousIndex];
}
}
if (minValue !== 100005) {
reachable[index] = minValue + 1;
}
}
return reachable[A.length - 1];
}
Python 100% answer.
For me the easiest solution was to locate all leaves within one fib jump of -1. Then consider each of these leaves to be index[0] and find all jumps from there.
Each generation or jump is recorded in a set until a generation contains len(A) or no more jumps can be found.
def gen_fib(n):
fn = [0,1]
i = 2
s = 2
while s < n:
s = fn[i-2] + fn[i-1]
fn.append(s)
i+=1
return fn
def new_paths(A, n, last_pos, fn):
"""
Given an array A of len n.
From index last_pos which numbers in fn jump to a leaf?
returns list: set of indexes with leaves.
"""
paths = []
for f in fn:
new_pos = last_pos + f
if new_pos == n or (new_pos < n and A[new_pos]):
paths.append(new_pos)
return path
def solution(A):
n = len(A)
if n < 3:
return 1
# A.append(1) # mark final jump
fn = sorted(gen_fib(100000)[2:]) # Fib numbers with 0, 1, 1, 2.. clipped to just 1, 2..
# print(fn)
paths = set([-1]) # locate all the leaves that are one fib jump from the start position.
jump = 1
while True:
# Considering each of the previous jump positions - How many leaves from there are one fib jump away
paths = set([idx for pos in paths for idx in new_paths(A, n, pos, fn)])
# no new jumps means game over!
if not paths:
break
# If there was a result in the new jumps record that
if n in paths:
return jump
jump += 1
return -1
https://app.codility.com/demo/results/training4GQV8Y-9ES/
https://github.com/niall-oc/things/blob/master/codility/fib_frog.py
Got 100%- solution in C.
typedef struct state {
int pos;
int step;
}state;
int solution(int A[], int N) {
int f1 = 0;
int f2 = 1;
int count = 2;
// precalculating count of maximum possible fibonacci numbers to allocate array in next loop. since this is C language we do not have flexible dynamic structure as in C++
while(1)
{
int f3 = f2 + f1;
if(f3 > N)
break;
f1 = f2;
f2 = f3;
++count;
}
int fib[count+1];
fib[0] = 0;
fib[1] = 1;
int i = 2;
// calculating fibonacci numbers in array
while(1)
{
fib[i] = fib[i-1] + fib[i-2];
if(fib[i] > N)
break;
++i;
}
// reversing the fibonacci numbers because we need to create minumum jump counts with bigger jumps
for(int j = 0, k = count; j < count/2; j++,k--)
{
int t = fib[j];
fib[j] = fib[k];
fib[k] = t;
}
state q[N];
int front = 0 ;
int rear = 0;
q[0].pos = -1;
q[0].step = 0;
int que_s = 1;
while(que_s > 0)
{
state s = q[front];
front++;
que_s--;
for(int i = 0; i <= count; i++)
{
int nextpo = s.pos + fib[i];
if(nextpo == N)
{
return s.step+1;
}
else if(nextpo > N || nextpo < 0 || A[nextpo] == 0){
continue;
}
else
{
q[++rear].pos = nextpo;
q[rear].step = s.step + 1;
que_s++;
A[nextpo] = 0;
}
}
}
return -1;
}
//100% on codility Dynamic Programming Solution. https://app.codility.com/demo/results/training7WSQJW-WTX/
class Solution {
public int solution(int[] A) {
int n = A.length + 1;
int dp[] = new int[n];
for(int i=0;i<n;i++) {
dp[i] = -1;
}
int f[] = new int[100005];
f[0] = 1;
f[1] = 1;
for(int i=2;i<100005;i++) {
f[i] = f[i - 1] + f[i - 2];
}
for(int i=-1;i<n;i++) {
if(i == -1 || dp[i] > 0) {
for(int j=0;i+f[j] <n;j++) {
if(i + f[j] == n -1 || A[i+f[j]] == 1) {
if(i == -1) {
dp[i + f[j]] = 1;
} else if(dp[i + f[j]] == -1) {
dp[i + f[j]] = dp[i] + 1;
} else {
dp[i + f[j]] = Math.min(dp[i + f[j]], dp[i] + 1);
}
}
}
}
}
return dp[n - 1];
}
}
Ruby 100% solution
def solution(a)
f = 2.step.inject([1,2]) {|acc,e| acc[e] = acc[e-1] + acc[e-2]; break(acc) if acc[e] > a.size + 1;acc }.reverse
mins = []
(a.size + 1).times do |i|
next mins[i] = -1 if i < a.size && a[i] == 0
mins[i] = f.inject(nil) do |min, j|
k = i - j
next min if k < -1
break 1 if k == -1
next min if mins[k] < 0
[mins[k] + 1, min || Float::INFINITY].min
end || -1
end
mins[a.size]
end
I have translated the previous C solution to Java and find the performance is improved.
import java.util.*;
class Solution {
private static class State {
int pos;
int step;
public State(int pos, int step) {
this.pos = pos;
this.step = step;
}
}
public static int solution(int A[]) {
int N = A.length;
int f1 = 0;
int f2 = 1;
int count = 2;
while (true) {
int f3 = f2 + f1;
if (f3 > N) {
break;
}
f1 = f2;
f2 = f3;
++count;
}
int[] fib = new int[count + 1];
fib[0] = 0;
fib[1] = 1;
int i = 2;
while (true) {
fib[i] = fib[i - 1] + fib[i - 2];
if (fib[i] > N) {
break;
}
++i;
}
for (int j = 0, k = count; j < count / 2; j++, k--) {
int t = fib[j];
fib[j] = fib[k];
fib[k] = t;
}
State[] q = new State[N];
for (int j = 0; j < N; j++) {
q[j] = new State(-1,0);
}
int front = 0;
int rear = 0;
// q[0].pos = -1;
// q[0].step = 0;
int que_s = 1;
while (que_s > 0) {
State s = q[front];
front++;
que_s--;
for (i = 0; i <= count; i++) {
int nextpo = s.pos + fib[i];
if (nextpo == N) {
return s.step + 1;
}
//
else if (nextpo > N || nextpo < 0 || A[nextpo] == 0) {
continue;
}
//
else {
q[++rear].pos = nextpo;
q[rear].step = s.step + 1;
que_s++;
A[nextpo] = 0;
}
}
}
return -1;
}
}
JavaScript with 100%.
Inspired from here.
function solution(A) {
const createFibs = n => {
const fibs = Array(n + 2).fill(null)
fibs[1] = 1
for (let i = 2; i < n + 1; i++) {
fibs[i] = fibs[i - 1] + fibs[i - 2]
}
return fibs
}
const createJumps = (A, fibs) => {
const jumps = Array(A.length + 1).fill(null)
let prev = null
for (i = 2; i < fibs.length; i++) {
const j = -1 + fibs[i]
if (j > A.length) break
if (j === A.length || A[j] === 1) {
jumps[j] = 1
if (prev === null) prev = j
}
}
if (prev === null) {
jumps[A.length] = -1
return jumps
}
while (prev < A.length) {
for (let i = 2; i < fibs.length; i++) {
const j = prev + fibs[i]
if (j > A.length) break
if (j === A.length || A[j] === 1) {
const x = jumps[prev] + 1
const y = jumps[j]
jumps[j] = y === null ? x : Math.min(y, x)
}
}
prev++
while (prev < A.length) {
if (jumps[prev] !== null) break
prev++
}
}
if (jumps[A.length] === null) jumps[A.length] = -1
return jumps
}
const fibs = createFibs(26)
const jumps = createJumps(A, fibs)
return jumps[A.length]
}
const A = [0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0]
console.log(A)
const s = solution(A)
console.log(s)
You should use a QUEUE AND NOT A STACK. This is a form of breadth-first search and your code needs to visit nodes that were added first to the queue to get the minimum distance.
A stack uses the last-in, first-out mechanism to remove items while a queue uses the first-in, first-out mechanism.
I copied and pasted your exact code but used a queue instead of a stack and I got 100% on codility.
100% C++ solution
More answers in my github
Inspired from here
Solution1 : Bottom-Top, using Dynamic programming algorithm (storing calculated values in an array)
vector<int> getFibonacciArrayMax(int MaxNum) {
if (MaxNum == 0)
return vector<int>(1, 0);
vector<int> fib(2, 0);
fib[1] = 1;
for (int i = 2; fib[fib.size()-1] + fib[fib.size() - 2] <= MaxNum; i++)
fib.push_back(fib[i - 1] + fib[i - 2]);
return fib;
}
int solution(vector<int>& A) {
int N = A.size();
A.push_back(1);
N++;
vector<int> f = getFibonacciArrayMax(N);
const int oo = 1'000'000;
vector<int> moves(N, oo);
for (auto i : f)
if (i - 1 >= 0 && A[i-1])
moves[i-1] = 1;
for (int pos = 0; pos < N; pos++) {
if (A[pos] == 0)
continue;
for (int i = f.size()-1; i >= 0; i--) {
if (pos + f[i] < N && A[pos + f[i]]) {
moves[pos + f[i]] = min(moves[pos]+1, moves[pos + f[i]]);
}
}
}
if (moves[N - 1] != oo) {
return moves[N - 1];
}
return -1;
}
Solution2: Top-Bottom using set container:
#include <set>
int solution2(vector<int>& A) {
int N = A.size();
vector<int> fib = getFibonacciArrayMax(N);
set<int> positions;
positions.insert(N);
for (int jumps = 1; ; jumps++)
{
set<int> new_positions;
for (int pos : positions)
{
for (int f : fib)
{
// return jumps if we reach to the start point
if (pos - (f - 1) == 0)
return jumps;
int prev_pos = pos - f;
// we do not need to calculate bigger jumps.
if (prev_pos < 0)
break;
if (prev_pos < A.size() && A[prev_pos])
new_positions.insert(prev_pos);
}
}
if (new_positions.size() == 0)
return -1;
positions = new_positions;
}
return -1;
}

My Code Gets cut and i have no idea why

public static int EncontrarCadena(char arrayTriangulo[][]) {
int aux = 0;
int area = 0;
int cantidadFilas = arrayTriangulo.length;
for (int i = 0; i < cantidadFilas; i++) {
int cantidadColumnas = arrayTriangulo[i].length;
for (int k = 0; k < cantidadColumnas; k++) {
if (arrayTriangulo[i][k] == '-') {
aux++;
} else if (arrayTriangulo[i][k] == '#') {
aux = 0;
}
if (aux%2!=0) {
int aux2 = ((aux + 1) / 2) - 1;
int aux4 = ((aux + 1) / 2) - 1;
int aux3 = aux;
int aux5 = aux3;
int a = 0;
int k2 = k;
while (aux2 != 0) {
for (int i2 = i + 1; i2 < cantidadFilas; i2++) {
for (int j = k2 - aux5 + 1; j < 2 * aux2 - 1; j++) {
if (arrayTriangulo[i2][j] == '-') {
aux3++;
} else if (arrayTriangulo[i2][j] == '#') {
break;
}
}
if (aux3 == aux + 2 * aux4 - 1) {
a++;
k2 = k2 + aux3 + 1;
aux2 = aux2 - 1;
aux4 = aux4 + 2 * ((aux + 1) / 2) - a;
aux5 = aux3;
}
}
}
if (aux2 == 0 && area < aux3) {
area = aux3;
}
}
}
aux = 0;
}
return area;
}
public static void main(String[] args) {
int filas = 5;
int columnas = 2 * filas - 1;
char arrayTriangulo[][] = new char[filas][columnas];
for (int i = (filas - 1); i > -1; i--) {
int aux = 2 * (filas - i) - 1;
for (int k = 0; k < columnas; k++) {
if (aux < 2 * filas - 1) {
if (k > (2 * filas - (aux)) / 2 && k < (columnas - (aux)) / 2 + aux) {
arrayTriangulo[i][k] = '-';
} else {
arrayTriangulo[i][k] = '-';
}
}
}
}
int area = EncontrarCadena(arrayTriangulo);
System.out.println(area);
}
So, This code get a Triangle made inside a 2d Array with the Following Format
---------
-------
-----
---
-
It's Supposed to count the area of smaller Triangles Inside of it and then return the are of the biguest triangle wich would be 25 (The sum of all the '-'). thing is the code isn't working and i have no idea why.
while (aux2 != 0) {
for (int i2 = i + 1; i2 < cantidadFilas; i2++) {
for (int j = k2 - aux5 + 1; j < 2 * aux2 - 1; j++) {
if (arrayTriangulo[i2][j] == '-') {
aux3++;
} else if (arrayTriangulo[i2][j] == '#') {
break;
}
}
if (aux3 == aux + 2 * aux4 - 1) {
a++;
k2 = k2 + aux3 + 1;
aux2 = aux2 - 1;
aux4 = aux4 + 2 * ((aux + 1) / 2) - a;
aux5 = aux3;
}
}
}
fails arround this part if i'm not mistaken

Large addition using String

Given two numbers as input, return the sum of the numbers. Note that the numbers can be very large and hence are provided as Strings
Sample Input #1:
add("2354725234782357","9999999999999999999999999988888888888")
Sample Output #1:
10000000000000000000002354714123671245
Implementation:
public String add(String str1, String str2) {
int max = str1.length() > str2.length() ? str1.length() : str2.length();
int n1[] = new int[max];
int n2[] = new int[max];
for (int i = 0; i < str1.length(); i++) {
n1[i] = str1.charAt(str1.length() - 1 - i);
}
for (int i = 0; i < str2.length(); i++) {
n2[i] = str2.charAt(str2.length() - 1 - i);
}
int carry = 0;
int sum[] = new int[max + 1];
int k = 0;
for (k = 0; k < max; k++) {
sum[k] = (n1[k] + n2[k] + carry) % 10;
if ((n1[k] + n2[k] + carry) >= 10) {
carry = 1;
} else {
carry = 0;
}
}
sum[max] = carry;
String result = "";
return result;
}
I have implemented my logic but I don't know how to get the output as a string.
Why don't use BigInteger this is much easier and still native java.
private static String add(String s1, String s2)
{
BigInteger n1 = new BigInteger(s1);
BigInteger n2 = new BigInteger(s2);
return n1.add(n2).toString();
}
Anyway, there is one bug in your Code. Dont cast char to int the ascii value is used, which is wrong. Parse it with Character.getNumericValue();
If you have done this, you can concat sum array to a string in reversed order.
Solution:
public static String add(String str1, String str2) {
int max = str1.length() > str2.length() ? str1.length() : str2.length();
int n1[] = new int[max];
int n2[] = new int[max];
for (int i = 0; i < str1.length(); i++)
{
// conver char to int
n1[i] = Character.getNumericValue(str1.charAt(str1.length() - 1 - i));
}
for (int i = 0; i < str2.length(); i++) {
// conver char to int
n2[i] = Character.getNumericValue(str2.charAt(str2.length() - 1 - i));
}
int carry = 0;
int sum[] = new int[max + 1];
int k = 0;
for (k = 0; k < max; k++) {
sum[k] = (n1[k] + n2[k] + carry) % 10;
if ((n1[k] + n2[k] + carry) >= 10) {
carry = 1;
} else {
carry = 0;
}
}
sum[max] = carry;
// concat array in reverse order
StringBuilder sb = new StringBuilder();
for(int i = sum.length - 1; i >= 0; i--)
sb.append(sum[i]);
return sb.toString();
}
Input
add("2354725234782357","9999999999999999999999999988888888888")
Output
10000000000000000000002354714123671245
There is a logic error in your code: you are adding the char value of each integer instead of the integer themselves. You can get the numeric value of a char using Character.getNumericValue(char ch).
Then, you can construct the resulting String by looping over the sum array. The loop must be done in reverse order (to get the correct order). Beware of the first value sum[max], if it is 0, we must not add it to the String (otherwise, we will get a value padded with a 0):
public static String add(String str1, String str2) {
int max = Math.max(str1.length(), str2.length());
int n1[] = new int[max];
int n2[] = new int[max];
for (int i = 0; i < str1.length(); i++) {
//n1[i] = str1.charAt(str1.length() - 1 - i);
n1[i] = Character.getNumericValue(str1.charAt(str1.length() - 1 - i));
}
for (int i = 0; i < str2.length(); i++) {
//n2[i] = str2.charAt(str2.length() - 1 - i);
n2[i] = Character.getNumericValue(str2.charAt(str2.length() - 1 - i));
}
int carry = 0;
int sum[] = new int[max + 1];
int k = 0;
for (k = 0; k < max; k++) {
sum[k] = (n1[k] + n2[k] + carry) % 10;
if ((n1[k] + n2[k] + carry) >= 10) {
carry = 1;
} else {
carry = 0;
}
}
sum[max] = carry;
StringBuilder sb = new StringBuilder();
if (sum[max] > 0) {
sb.append(String.valueOf(sum[max]));
}
for (int i = max - 1; i >= 0; i--) {
sb.append(String.valueOf(sum[i]));
}
return sb.toString();
}
Note that you can also replace
int max = str1.length() > str2.length() ? str1.length() : str2.length();
with
int max = Math.max(str1.length(), str2.length());
I have modified some code:(you can avoid array creation)
public static String add(String str1, String str2) {
int carry=0;
StringBuilder sum=new StringBuilder();
int l1=str1.length();
int l2=str2.length();
while(l1>0 && l2>0){
int s=Character.getNumericValue(str1.charAt(--l1))+Character.getNumericValue(str2.charAt(--l2))+carry;
if(s<10){
sum.append(s);
}else{
sum.append(s%10);
carry=s/10;
}
}
if(l2>0){
while(l2>0){
int s=Character.getNumericValue(str2.charAt(--l2))+carry;
if(s<10){
sum.append(s);
}else{
sum.append(s%10);
carry=s/10;
}
}
}
if(l1>0){
while(l2>0){
int s=Character.getNumericValue(str1.charAt(--l1))+carry;
if(s<10){
sum.append(s);
}else{
sum.append(s%10);
carry=s/10;
}
}
}
if(carry>0){
sum.append(carry);
}
return sum.reverse().toString();
}
You can use a StringBuilder to append all the digits from your int[] from max to 0.
StringBuilder sb = new StringBuilder();
for (int i=max; i>=0; i--)
{
sb.append(String.valueOf(sum[i]));
}
String result = sb.toString();
You can also improve this to skip leading zeroes if you want:
boolean leadingZero = true;
StringBuilder sb = new StringBuilder();
for (int i=max; i>=0; i--)
{
if (sum[i] != 0)
{
leadingZero=false;
}
if (!leadingZero)
{
sb.append(String.valueOf(sum[i]));
}
}
String result = sb.toString();

Find triangles in a list of random numbers

I'm taking each element as "sum", "first" and "sec". If (first + sec < sum) I'll make a hashset(tmp) of these 3 and put this hashset into a larger hashset(triangle) containing all tmp hashsets. This removes duplicate combinations of 3 numbers. Here's my code. It works but is there any better solution?
public void findTriangle(int[] a){
HashSet<HashSet<Integer>> triangle = new HashSet<HashSet<Integer>>();
HashSet<Integer> tmp;
for(int i=0;i<a.length;i++){
int sum=a[i];
for(int j=0;j<a.length;j++){
int first = a[j];
if(first!=sum){
for(int k=0;k<a.length;k++){
int sec = a[k];
if(sec!=first && sec!=sum && (first + sec < sum)){
tmp = new HashSet<Integer>();
tmp.add(first);
tmp.add(sec);
tmp.add(sum);
triangle.add(tmp);
}
}
}
}
}
for(HashSet<Integer> hs : triangle)
System.out.println(hs);
}
Sort the array and add the triplets to a list -
public static ArrayList<ArrayList<Integer>> get(int[] input) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
if (input.length < 3) {
return result;
}
Arrays.sort(input);
for (int i = 0; i < input.length - 2; i++) {
int k = i + 2;
for (int j = i + 1; j < input.length; j++) {
while (k < input.length && input[i] + input[j] > input[k]) {
ArrayList<Integer> inner = new ArrayList<Integer>();
inner.add(input[i]);
inner.add(input[j]);
inner.add(input[k]);
result.add(inner);
k++;
}
}
}
return result;
}
Not so optimal works yet. I tried testing the above two solutions and they seemed to not work. May be i was missing something. Hence decided to post my tested solution here. It does not check for duplicates.
Condition to find a triangle: http://www.wikihow.com/Determine-if-Three-Side-Lengths-Are-a-Triangle
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Arrays;
class Triangle {
int a;
int b;
int c;
public Triangle(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
}
#Override
public String toString() {
return this.a + " " + this.b + " " + this.c;
}
}
public class FindTriangle {
public List<Triangle> findTriangle(List<Integer> points) {
List<Triangle> result = new ArrayList<Triangle>();
System.out.println("Entered");
for (int i = 0; i < points.size(); i++) {
int pt0 = points.get(i);
System.out.println("Entered i:" + i);
for (int j = i + 1; j < points.size() - 2; j++) {
int pt1 = points.get(j);
int pt2 = points.get(j + 1);
Boolean isTri = isTriangle(pt0, pt1, pt2);
if (isTri.equals(Boolean.TRUE)) {
Triangle t = new Triangle(pt0, pt1, pt2);
result.add(t);
}
}
for (int j = 0; j < (i - 1) && j > 0; j++) {
int pt1 = points.get(j);
int pt2 = points.get(j + 1);
Boolean isTri = isTriangle(pt0, pt1, pt2);
if (isTri.equals(Boolean.TRUE)) {
Triangle t = new Triangle(pt0, pt1, pt2);
result.add(t);
}
}
// final
int pt1, pt2;
if (i == 0) {
pt1 = points.get(i + 1);
pt2 = points.get(points.size() - 1);
} else if (i == points.size() - 1) {
pt1 = points.get(0);
pt2 = points.get(i - 1);
} else {
pt1 = points.get(i + 1);
pt2 = points.get(i - 1);
}
Boolean isTri = isTriangle(pt0, pt1, pt2);
if (isTri.equals(Boolean.TRUE)) {
Triangle t = new Triangle(pt0, pt1, pt2);
result.add(t);
}
}
return result;
}
public Boolean isTriangle(Integer pt1, Integer pt2, Integer pt3) {
System.out.println("Pt1, Pt2, Pt3: " + pt1 + ":" + pt2 + ":" + pt3);
if ((pt1 + pt2) > pt3 && (pt1 + pt3) > pt2 && (pt2 + pt3) > pt1) {
System.out.println("This is triangle");
return Boolean.TRUE;
}
return Boolean.FALSE;
}
public ArrayList<ArrayList<Integer>> getTri(int[] input) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
if (input.length < 3) {
return result;
}
Arrays.sort(input);
for (int i = 0; i < input.length - 2; i++) {
int k = i + 2;
for (int j = i + 1; j < input.length; j++) {
while (k < input.length && input[i] + input[j] > input[k]) {
ArrayList<Integer> inner = new ArrayList<Integer>();
inner.add(input[i]);
inner.add(input[j]);
inner.add(input[k]);
result.add(inner);
k++;
}
}
}
return result;
}
public void findTriangleW(int[] a) {
HashSet<HashSet<Integer>> triangle = new HashSet<HashSet<Integer>>();
HashSet<Integer> tmp;
for (int i = 0; i < a.length; i++) {
int sum = a[i];
for (int j = 0; j < a.length; j++) {
int first = a[j];
if (first != sum) {
for (int k = 0; k < a.length; k++) {
int sec = a[k];
if (sec != first && sec != sum && (first + sec < sum)) {
tmp = new HashSet<Integer>();
tmp.add(first);
tmp.add(sec);
tmp.add(sum);
triangle.add(tmp);
}
}
}
}
}
for (HashSet<Integer> hs : triangle)
System.out.println(hs);
}
public static void main(String[] args) {
FindTriangle f = new FindTriangle();
List<Integer> points = new ArrayList<Integer>();
points.add(1);
points.add(5);
points.add(10);
points.add(7);
System.out.println("Printing final results");
List<Triangle> result = f.findTriangle(points);
for (int i = 0; i < result.size(); i++) {
System.out.println(result.get(i).toString());
}
}
}

Alternate Solution for maxBlock from CodingBat

Solving this problem from codingBat
Given a string, return the length of the largest "block" in the
string. A block is a run of adjacent chars that are the same.
maxBlock("hoopla") → 2
maxBlock("abbCCCddBBBxx") → 3
maxBlock("") → 0
I was trying to solve it using one for loop as below:
public int maxBlock(String str) {
int maxCounter=1;
int counter=1;
if(str.length()==0)
{
return 0;
}
for(int i=0;i<str.length()-1;i++)
{
if(str.substring(i,i+1).equals(str.substring(i+1,i+2)))
{
counter++;
}
if(counter>maxCounter)
{
maxCounter=counter;
counter=0;
}
}
return maxCounter;
}
It beats all the cases apart from one. Can anybody show a solution with one for loop?
Sorry for mentioning late but you can't use REGEX or anything from collections framework.
I think you get it wrong in certain edge cases:
public int yourMaxBlock(String str) {
int maxCounter = 1;
int counter = 1;
if (str.length() == 0) {
return 0;
}
for (int i = 0; i < str.length() - 1; i++) {
if (str.substring(i, i + 1).equals(str.substring(i + 1, i + 2))) {
counter++;
}
if (counter > maxCounter) {
maxCounter = counter;
counter = 0;
}
}
return maxCounter;
}
public int myMaxBlock(String str) {
int maxCounter = 1;
int counter = 1;
if (str.isEmpty()) {
return 0;
}
for (int i = 1; i < str.length(); i++) {
if (str.charAt(i - 1) == str.charAt(i)) {
if (++counter > maxCounter) {
maxCounter = counter;
}
} else {
counter = 1;
}
}
return maxCounter;
}
public void test() {
String[] tests = new String[]{
"", "+", "++", "+++,++,++,+", "+,++,+++,++,", "+,++,+++,++++", "+++++,++,+++,++++"
};
for (String s : tests) {
int myMax = myMaxBlock(s);
int yourMax = yourMaxBlock(s);
System.out.println("myMaxBlock(" + s + ") = " + myMax + (myMax != yourMax ? " WRONG! you have " + yourMax : ""));
}
}
prints
myMaxBlock() = 0
myMaxBlock(+) = 1
myMaxBlock(++) = 2
myMaxBlock(+++,++,++,+) = 3
myMaxBlock(+,++,+++,++,) = 3
myMaxBlock(+,++,+++,++++) = 4 WRONG! you have 3
myMaxBlock(+++++,++,+++,++++) = 5 WRONG! you have 4
You can use a Pattern matcher "(.)(\\1)*" that look for repeated char in the String , Here is the code :
public int maxBlock(String str) {
Pattern pattern = Pattern.compile("(.)(\\1)*");
Matcher matcher = pattern.matcher(str);
int max = 0;
while (matcher.find()) {
max = Math.max(max, matcher.group().length());
}
return max;
}
I'm a little late to the party, but here's my CodingBat solution:
public int maxBlock(String str) {
int max = 0;
int count = 1;
char o = ' ';
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (c == o) {
count++;
if (count > max) { max = count; }
} else {
count = 1;
if (count > max) { max = count; }
}
o = c;
}
return max;
}
Here's a solution based loosely on yours. Note the use of charAt for a neater looking code example.
This starts at the second character of the string and looks backwards to see if we are still encountering the same character. If so, the counter increases. When we finish a string of identical chars, we compare against the max length found thus far and update if necessary.
public static int maxBlock(String str) {
int maxCounter = 1;
int counter = 1;
if (str.length() == 0) {
return 0;
}
for (int i = 1; i < str.length(); i++) {
if (str.charAt(i - 1) == str.charAt(i)) {
counter++;
} else {
// end of a run
if (counter > maxCounter) {
maxCounter = counter;
}
counter = 1;
}
}
return Math.max(maxCounter, counter);
}
Just use one for loop. I think here is another way.
public int maxBlock(String str) {
int len = str.length();
int temp=(len>0)?1:0;
int r =0;
for(int i=1; i<len; i++){
if(str.charAt(i) == str.charAt(i-1)){
temp++;
}
else{
r = (temp>r)?temp:r;
temp=1;
}
}
r = (temp>r)?temp:r;
return r;
}
public int maxBlock(String str) {
int max = 0;
for(int i = 0 ; i < str.length() ; i ++ ) {
char compareChar = str.charAt(i);
int count = 0;
while (i + 1 < str.length()
&& compareChar == str.charAt(i+1)) {
i++;
count ++;
}
if (max < count + 1) {
max = count + 1;
}
}
return max;
}
Here's my solution. It's simpler than you think.
public int maxBlock(String str)
{
//create a counter to return
int counter = 0;
//create a temporary variable to store a running total.
int temp = 1;
//Start on the first character and test to see if the second
//character equals the first.
for (int i = 1; i < str.length(); i++)
{
//If it does, we increment the temp variable.
if (str.charAt(i) == str.charAt(i-1))
{
temp++;
}
//If it doesn't, we wipe the temp variable and start from one.
else
{
temp = 1;
}
//If the temporary variable exceeds the counter amount, we make
//the counter variable equal to the temp variable.
if (temp > counter)
{
counter = temp;
}
}
//Return the counter.
return counter;
}
public int maxBlock(String str) {
int maxLength = 0;
Map<String,Integer> map = new HashMap<String,Integer>();
for(int i = 0; i< str.length(); i++){
String key = str.substring(i,i+1);
if(i!=0 && str.charAt(i) == str.charAt(i-1) && map.containsKey(key)){
map.put(key, map.get(key)+1);
}
else{
map.put(key,1);
}
}
for(Map.Entry<String,Integer> entry : map.entrySet()){
if(maxLength <entry.getValue()){
maxLength = entry.getValue();
}
}
return maxLength;
}
public int maxBlock(String str) {
int count = 0;
int i = 0;
int maxcount = 0;
if (str.length() == 0) return 0;
while (i < str.length() - 1) {
if (str.charAt(i) == str.charAt(i + 1)) {
count++;
if (count > maxcount) {
maxcount = count;
}
} else count = 0;
i++;
}
return maxcount + 1;
}
public int maxBlock(String str) {
int tcount = 0;
if (str.length() < 1) {
return 0;
}
for (int i = 0; i < str.length(); i++) {
int count = 0;
for (int j = i; j < str.length(); j++) {
if (str.charAt(i) == str.charAt(j)) {
count++;
} else
break;
}
if (count > tcount) {
tcount = count;
}
i += count - 1;
}
return tcount;
}
this is easier it totally works.
int i = 0;
int j = 0;
while(i < inner.length && j < outer.length) {
if(inner[i] > outer[j]) {
j++;
} else if(inner[i] < outer[j]) {
return false;
} else {
i++;
}
}
if(i != inner.length)
return false;
return true;
}
Here My code for this
public int maxBlock(String str) {
int count = 1;
for(int i=0;i<str.length()-1;i++){
int count2 = 0;
if(str.substring(i,i+1).equals(str.substring(i+1,i+2) )){
for(int j = i ; j < str.length();j++){
if(str.substring(i,i+1).equals(str.substring(j,j+1))){
++count2;
}
else{
break;
}
}
}
if(count2 > count){
count = count2;
}
}
if(str.isEmpty())return 0;
return count;
}

Categories

Resources