0-1 knapsack TLE - algorithm

I was solving 0-1 knapsack problem (src:https://www.interviewbit.com/problems/0-1-knapsack/)
and would like to understand why I got TLE and know how to get rid of TLE .
My solution : (which showed TLE in hard case)
int knapsack(vector<int> A , vector<int> B, int weight , int n , vector<vector<int>> &dp ){
if(weight==0 || n==0){
// dp[weight][n] = 0;
return 0 ;
}
if(dp[weight][n]!=(-1)){
return dp[weight][n];
}
if(B[n-1]<=weight){
dp[weight][n] = max( (knapsack(A,B,weight,n-1,dp)) , (A[n-1] + knapsack(A,B,weight-B[n-1],n-1,dp)) );
return max( (knapsack(A,B,weight,n-1,dp)) , (A[n-1] + knapsack(A,B,weight-B[n-1],n-1,dp)) );
}
// if(B[n-1]>weight){
else{
dp[weight][n] = knapsack(A,B,weight,n-1,dp);
return knapsack(A,B,weight,n-1,dp);
}
}
int Solution::solve(vector<int> &A, vector<int> &B, int C) {
int N = A.size();
// n rows and weights written vertically in columns
vector<vector<int>> dp(C+1, vector<int> (N+1,-1));
return knapsack(A,B,C,N,dp);
}
One solution which I found in discussion tab and does not get TLE which is exactly same as my solution :
int knapsack(vector<int>& wt, vector<int>& val, int W, int n, vector<vector<int>>& dp)
{
if(n == 0 || W == 0)
return 0;
if(dp[n][W] != -1)
return dp[n][W];
if(wt[n-1] <= W)
return dp[n][W] = max(val[n-1] + knapsack(wt, val, W-wt[n-1], n-1, dp), knapsack(wt, val, W, n-1, dp));
else
return dp[n][W] = knapsack(wt, val, W, n-1, dp);
}
int Solution::solve(vector<int> &val, vector<int> &wt, int W)
{
int n = wt.size();
vector<vector<int>> dp(n+1 , vector<int> (W+1, -1));
return knapsack(wt, val, W, n, dp);
}
Is it possible that using a bigger variable name caused me a TLE in the hard case ?

You do too many recursive calls.
knapsack is not a pure function. It has side effect of modifying dp, and the compiler is not smart enough to figure out that a second call in the else branch
dp[weight][n] = knapsack(A,B,weight,n-1,dp);
return knapsack(A,B,weight,n-1,dp);
is redundant. Help the compiler and optimize it out manually:
dp[weight][n] = knapsack(A,B,weight,n-1,dp);
return dp[weight][n];
or, just as in the other solution
return dp[weight][n] = knapsack(A,B,weight,n-1,dp);
Ditto for the if branch,
(And no, variable names do not affect performance).

Related

Find the maximum number of pieces a rod can be cut

Here is the complete problem statement:
Given a rope of length n, you need to find the maximum number of pieces
you can make such that the length of every piece is in set {a, b, c} for
the given three values a, b, c
I know that the optimal solution can be achieved through Dynamic Programming, however, I have not learned that topic yet and I need to solve this problem recursively. With recursion, the main thing is to identify a subproblem and that's what I'm mainly having difficulty with doing. Can anyone give me an intuitive way to think of this problem? Sort of like a higher level description of the recursion if that makes sense. Is there an easier problem similar to this that I can try first that would help me solve this?
Thanks in advance.
It's already quite simple, with recursion we can just check all posibilities, in one step we can either cut away a piece of length a, b, or c so from problem of size n we get sup-problem of smaller size n-x
Of course we need a base case, so when n=0 we have succeeded so we can return 0, in case of n < 0 we have failed so we can return some negative infinity constant
Sample pseudo-code:
int solve(int n){
if(n < 0) return -123456789; //-Infinity
if(n == 0) return 0;
return 1 + max(solve(n-a), solve(n-b), solve(n-c));
}
going to dynamic programming is as simple as setting up memo lookup table
int solve(int n){
if(n < 0) return -123456789; //-Infinity
if(n == 0) return 0;
if(n in memo)return memo[n]
return memo[n] = 1 + max(solve(n-a), solve(n-b), solve(n-c));
}
int maxcut(int n, int a,int b,int c)
{
if(n==0) return 0;
if(n<0) return 1;
int result = max( maxcut(n-a,a,b,c), maxcut(n-b,a,b,c), maxcur(n-c,a,b,c));
if(res == -1) return -1;
return(result+1)
}
The way we should tackle the recursion problem is:
Finding the recursion case (Finding the subproblems)
Finding the base case (The last subproblem case we cannot break in subproblems)
Specific to this problem :
Recursion case: Cutting rope we all the possible values till we cannot break it further smaller subproblem.
Base case: a. It can be completely cut. (valid try)
b.It can't be completely cut. (invalid try)
int maxcut(int n, int a,int b,int c)
{
if(n==0) return 0; //base case a.
if(n<0) return -1; //base case b.
int result = max( maxcut(n-a,a,b,c), maxcut(n-b,a,b,c), maxcur(n-c,a,b,c)); //subproblems for all the cases
if(res == -1) return -1; // boundry coundtion
return(result+1); //to count the valid conditions and return to parent
}
here is the complete code for your problem
#include <iostream>
using namespace std;
int max(int a, int b, int c)
{
if (a > b)
{
if (a > c)
{
return a;
}
else
{
return c;
}
}
else
{
if (b > c)
{
return b;
}
else
{
return c;
}
}
}
int maxpiece(int l, int a, int b, int c)
{
int r;
if (l == 0)
{
return 0;
}
if (l<0)
{
return -1;
}
r = max(maxpiece(l-a, a, b, c), maxpiece(l-b, a, b, c), maxpiece(l-c, a, b, c));
if (r == -1)
return -1;
return r + 1;
}
int main()
{
int lenth;
cout << "enter rope lenth ";
cin >> lenth;
int p1, p2, p3;
cout << endl
<< "enter the only three parameters in which rope can be cut ";
cin >> p1 >> p2 >> p3;
cout << endl
<<"ans = "<< maxpiece(lenth, p1, p2, p3);
}
int cutRope(int n, int a, int b, int c){
// Base cases
if(n == 0) return 0;
if(n < 0) return -1;
int res = max(max(cutRope(n - a, a, b, c), cutRope(n - b, a, b, c)), cutRope(n - c, a, b, c));
if(res == -1) return -1;
return res + 1;
}
int main() {
cout << cutRope(23, 11, 9, 12) << endl;
return 0;
}

Looking for a data structure to perform range element update efficiently

I currently have the following data structure:
class DataStructure {
public:
DataStructure(int n) : m_data(n, 0) {
}
void update(int i, int j, int value) {
for (int k = i; k <= j; ++k) {
m_data[k] = max(m_data[k], value);
}
}
void reset(int i) {
m_data[i] = 0;
}
int query(int i) {
return m_data[i];
}
private:
vector<int> m_data;
};
So what it does is rather simple:
Initially there is a vector of n integers initialised to zero.
update(i, j, value) updates the elements in the range [i, j] to be the max of the given value and their respective current value. The given value is in the range of [0, n].
reset(i) resets the value at index i to 0.
query(i) returns the value at index i.
I need to perform n updates, n resets and n query operations. Currently this code takes O(n*n) time, due to the update operation being O(n) in general.
I am wondering if there are some smart ways to improve this to O(n*log n) time (or better) for n updates, n resets and n query operations, while maintaining O(n) space complexity?
Thanks for #qwertman for the explanation here is an algorithm that should work
#include <iostream>
#include <cstdio>
using namespace std;
#define max(a, b) (a>b?a:b)
int tree[100005], lazy[100005];
void init(int idx, int l, int r){
if(l>r)
return ;
if(l==r){
tree[idx] = 0;
lazy[idx] = -1;
}
else {
tree[idx] = 0;
lazy[idx] = -1;
int mid = (l+r)/2;
init(2*idx, l, mid);
init(2*idx+1, mid+1, r);
}
}
// l and r is for internal use the range a-b has to be updated
void update(int idx, int l, int r, int a, int b, int val, bool isReset){
if(l>r || b<l || a>r){
return;
}
// printf("idx=%d l=%d r=%d a=%d b=%d val=%d\n",idx,l,r,a,b,val);
if(lazy[idx] != -1){
tree[idx] = max(tree[idx], lazy[idx]);
lazy[2*idx] = max(lazy[2*idx], lazy[idx]);
lazy[2*idx+1] = max(lazy[2*idx+1], lazy[idx]);
lazy[idx] = -1;
}
if(l>=a && r<=b){
// printf("updating\n");
tree[idx] = max(tree[idx], val);
if(isReset){
tree[idx] = val;
}
lazy[2*idx] = max(lazy[2*idx], val);
lazy[2*idx+1] = max(lazy[2*idx+1], val);
lazy[idx] = -1;
}
else {
int mid = (l+r)/2;
update(2*idx, l, mid, a, b, val, isReset);
update(2*idx+1, mid+1, r, a, b, val, isReset);
tree[idx] = max(tree[2*idx], tree[2*idx+1]);
}
}
int query(int idx, int l, int r, int a){
if(l>r || a<l || a>r){
return -1;
}
// printf("idx=%d l=%d r=%d a=%d\n",idx,l,r,a);
if(lazy[idx] != -1){
tree[idx] = max(tree[idx], lazy[idx]);
lazy[2*idx] = max(lazy[2*idx], lazy[idx]);
lazy[2*idx+1] = max(lazy[2*idx+1], lazy[idx]);
lazy[idx] = -1;
}
if(l==a && r==a){
// printf("----l=%d r=%d a=%d tree=%d\n",l,r,a,tree[idx]);
return tree[idx];
}
else {
int mid = (l+r)/2;
int left = query(2*idx, l, mid, a);
int right = query(2*idx+1, mid+1, r, a);
return max(left, right);
}
}
int main() {
// initializing everything to 0
init(1, 1, 10);
// updating range 1-4 with value 7
update(1, 1, 10, 1, 4, 7, false);
// query for 3 should result in 7
cout << query(1, 1, 10, 3) << endl;
// updating 3-3 with value 9
update(1, 1, 10, 3, 3, 9, false);
// should give 9
cout << query(1, 1, 10, 3) << endl;
// isReset is set to true, so the function will do a hard reset
update(1, 1, 10, 3, 3, 0, true);
// should give 0
cout << query(1, 1, 10, 3) << endl;
return 0;
}
you can run this code at http://ideone.com/Mkp4dQ
some useful links for learning segment tree with lazy propagation hackerearth
Geeksforgeeks

Find all possible paths through a maze

I'm trying to create a program that will traverse a randomly generated maze where 1's are open and 0's are walls. starting in the top left and ending in the bottom right. The path can go up, down, left, and right.
Currently, my program gives me a solution, but I'm having trouble getting it to print more than one path.
I've read several different versions of this problem, but I'm unable to find one quite with my parameters.
Here's my code, I omitted the part where I randomly generate my maze.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
int n, minMatrix, solIndex = 1, minLen = 10000000; //I use the latter 3 variables in order to find the shortest path, not relevant for now
bool solveMaze(int mat[n][n],int x, int y, int sol[][n], int count){
int i, j;
if((!(x >= 0 && x <n && y >=0 && y < n)) || mat[x][y] == 0 || sol[x][y] == 1){
return false;
}
if(x == n-1 && y == n-1){
sol[x][y] = 1;
printf("Solution %d is:\n", solIndex);
for(i = 0; i < n; i++)
{
for( j=0;j<n;j++)
{
printf("%d", sol[i][j]);
}
printf("\n");
}
if(count<minLen)
{
minLen = count;
minMatrix = solIndex;
}
solIndex +=1;
sol[x][y] = 0;
return true;
}
sol[x][y] = 1;
if(solveMaze(mat, x+1, y, sol, count+1)){
return true;
}
if(solveMaze(mat, x-1, y, sol, count+1)){
return true;
}
if(solveMaze(mat, x, y+1, sol, count+1)){
return true;
}
if(solveMaze(mat, x, y-1, sol, count+1)){
return true;
}
sol[x][y] = 0;
return false;
}
I've omitted the part of my main where I randomly generate my maze.
int main(){
if(!solveMaze(**mat, 0, 0, sol, 0)){
printf("No possible paths, run program again\n");
}
else{
printf("the shortest path is %d\n", minMatrix);
}
}
For instance if I have the maze
1100111111
1101111111
1111110110
1110011111
1101101011
1111101011
1110111101
1100111111
1110111011
1101101111
It gives me the first path that it finds
1000000000
1001100000
1111110000
1100011000
1100001000
1100001000
1100001000
1100001011
1100001011
1100001111
Though it takes a roundabout way of getting there, due to the preferences of going in order of down, up, right, and left, it is still one path.
So ultimately, I'm not sure how to iterate for multiple paths.
Straightforward fully working solution using the example maze from this similar question (which was marked as duplicate but was standalone compilable): Find all paths in a maze using DFS
It uses a simple DFS with straightforward recursion, which seems the same approach as in the question here. It keeps track of the current track in a single string instance and modifies the maze in place to block off the current track.
#include <iostream>
#include <string>
const int WIDTH = 6;
const int HEIGHT = 5;
void check(int x, int y, int dest_x, int dest_y,
int (&maze)[HEIGHT][WIDTH], std::string& path) {
if (x < 0 || y < 0 || x >= WIDTH|| y >= HEIGHT || !maze[y][x]) {
return;
}
int len = path.size();
path += (char) ('0' + x);
path += ',';
path += (char) ('0' + y);
if (x == dest_x && y == dest_y) {
std::cout << path << "\n";
} else {
path += " > ";
maze[y][x] = 0;
check (x + 0, y - 1, dest_x, dest_y, maze, path);
check (x + 0, y + 1, dest_x, dest_y, maze, path);
check (x - 1, y + 0, dest_x, dest_y, maze, path);
check (x + 1, y + 0, dest_x, dest_y, maze, path);
maze[y][x] = 1;
}
path.resize(len);
}
int main() {
int maze[HEIGHT][WIDTH] = {
{1,0,1,1,1,1},
{1,0,1,0,1,1},
{1,1,1,0,1,1},
{0,0,0,0,1,0},
{1,1,1,0,1,1}};
std::string path;
check(0, 0, 4, 3, maze, path);
return 0;
}
Runnable version: https://code.sololearn.com/cYn18c5p7609
i finally found you the solution to your question. but honestly it's not a solution that i did develope, some other people (namely: Schröder) had this idea before!
the problem is described by Schröder, but have a look at the german translation speaking of permutating a binary tree.
transform your path and all reachable nodes into a binary tree and permutate it! (but be warned, there may be many many solutions)
as you can see these are all solutions for crossing a 4x4 square (missing the mirrored part, but thats alas).

DP memoized approach for Longest common substring

can anyone provide the memoized approach for longest common substring between two strings.I know the bottom solution but I am not able to think in top-down manner.
Expected time complexity-O(n^2)
TOP-DOWN APPROACH
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
string X, Y; //input strings
int ans, dp[105][105]; // ans : answer
int LCS(int n, int m) //our function return value of (n,m) state
{ // so that we can use the result in (n+1,m+1) state
if(n == 0 || m == 0) return 0; //in case of match in (n+1,m+1) state
if(dp[n][m] != -1) return dp[n][m];
LCS(n-1,m); //to visit all n*m states (try example: X:ASDF
LCS(n,m-1); // we call these states first Y:ASDFF)
if(X[n-1] == Y[m-1])
{
dp[n][m] = LCS(n-1,m-1) + 1;
ans = max(ans, dp[n][m]);
return dp[n][m];
}
return dp[n][m] = 0;
}
int main()
{
int t; cin>>t;
while(t--)
{
int n, m; cin>>n>>m; //length of strings
cin>>X>>Y;
memset(dp, -1, sizeof dp);
ans = 0;
LCS(n, m);
cout<<ans<<'\n';
}
return 0;
}
Memoization with recursion works with top-down approach.
Taking LCS example using DP from Cormen into consideration below is the pseudo code describing how it will work.
MEMOIZED-LCS-LENGTH(X,Y)
m<-length[X]
n<-length[Y]
for(i<-1 to m)
do for(j<-1 to n)
c[i,j]<- -1
for(i<-1 to m)
c[i,0]<-0
for(j<-1 to n)
c[0,j]<-0
return RECURSIVE-LCS-LENGTH(X,Y,1,1)
RECURSIVE-LCS-LENGTH(X,Y,i,j)
if(c[i,j]!=-1)
return c[i,j]
//Above 2 line fetches the result if already present, instead of computing it again.
if(x[i]==y[j])
then c[i,j]<-RECURSIVE-LCS-LENGTH(X,Y,i+1,j+1)+1
else
c1<- RECURSIVE-LCS-LENGTH(X,Y,i+1,j)
c2<-RECURSIVE-LCS-LENGTH(X,Y,i,j+1)
if(c1<c2)
then c[i,j]<-c1
else c[i,j]<-c2
return c[i,j]
Java Solution:
class Solution {
public int findLength(int[] A, int[] B) {
int[][] cache = new int[A.length][B.length];
Arrays.stream(cache).forEach(a->Arrays.fill(a,-1));
int[] res = new int[1];
findLength(0, 0, A, B, cache, res);
return res[0];
}
public static int findLength(int a, int b, int[] A, int[] B, int[][] cache, int[] res){
if( a >= A.length || b >= B.length )
return 0;
if(cache[a][b] != -1){
return cache[a][b];
}
if(A[a] == B[b]){
cache[a][b] = 1 + findLength(a+1,b+1,A,B,cache,res);
// remember you can not return here: why? see case: s1 = 1,2,3 s2=1,4,1,2,3
}
// try out other possiblities and update cache
findLength(a+1,b,A,B,cache,res);
findLength(a,b+1,A,B,cache,res);
//you can avoid this and find max value at end in cache
res[0] = Math.max(res[0],cache[a][b]);
//at this point cache might have -1 or updated value, if its -1 make it to 0 as this location is visited and no common substring is there from here
cache[a][b] = Math.max(0,cache[a][b]);
return cache[a][b];
}
}
Recursion plus memoization in python. Please note this code is partially accepted on Hackerearth and Geeksforgeeks.For larger test cases, it is giving MLE.
import sys
sys.setrecursionlimit(1000000)
maxlen=0
t=None
def solve(s1, s2, n, m):
global maxlen, t
if n<=0 or m<=0:
return 0
if t[n][m]!=-1:
return t[n][m]
if s1[n-1]==s2[m-1]:
temp=1+solve(s1, s2, n-1, m-1)
maxlen=max(maxlen, temp)
t[n][m]=temp
return temp
t[n][m]=0
return 0
class Solution:
def longestCommonSubstr(self, S1, S2, n, m):
global maxlen, t
maxlen=0
t=[[-1]*(m+1) for i in range(n+1)]
for i in range(n+1):
for j in range(m+1):
solve(S1, S2, i, j)
return maxlen
if __name__=='__main__':
S1=input().strip()
S2=input().strip()
n=len(S1)
m=len(S2)
ob = Solution()
print(ob.longestCommonSubstr(S1, S2, n, m))
An easy solution is described below. Here memo[n][m] does not store the length of
greatest substring but you can store the greatest substring in pointer maxi as follows:
#include<iostream>
#include<string>
using namespace std;
int lcs(string X,string Y,int n,int m,int *maxi,int memo[][8]) {
if(n==0||m==0) {
return 0;
}
int k=0;
int j=0;
if(memo[n-1][m-1]!=-1) {
return memo[n-1][m-1];
}
if(X[n-1]==Y[m-1]) {
memo[n-1][m-1] = 1+lcs(X,Y,n-1,m-1,maxi,memo);
if(*maxi<memo[n-1][m-1])
*maxi=memo[n-1][m-1];
}
else {
memo[n-1][m-1]=0;
}
int l = lcs(X,Y,n-1,m,maxi,memo);
int i = lcs(X,Y,n,m-1,maxi,memo);
return memo[n-1][m-1];
}
int main()
{
int n,m;
string X = "abcdxyze";
//string X = "abcd";
string Y = "xyzabcde";
n=X.length();
m=Y.length();
int memo[n][8];
for(int i=0;i<n;i++) {
for(int j=0;j<m;j++) {
memo[i][j]=-1;
}
}
int maxi=0;
int k = lcs(X,Y,n,m,&maxi,memo);
cout << maxi;
return 0;
}
class Solution {
public:
int t[1005][1005];
int maxC = 0;
int recur_memo(vector<int>& nums1, vector<int>& nums2, int m, int n) {
if(t[m][n] != -1)
return t[m][n];
if(m == 0 || n == 0)
return 0;
int max_substring_ending_here = 0;
//Example : "abcdezf" "abcdelf"
//You see that wowww, string1[m-1] = string2[n-1] = 'f' and you happily
go for (m-1, n-1)
//But you see, in future after a gap of 'l' and 'z', you will find
"abcde" and "abcde"
if(nums1[m-1] == nums2[n-1]) {
max_substring_ending_here = 1 + recur_memo(nums1, nums2, m-1, n-1);
}
//May be you find better results if you do (m-1, n) and you end up
updating maxC with some LAAARGEST COMMON SUBSTRING LENGTH
int decrease_m = recur_memo(nums1, nums2, m-1, n); //stage (m-1, n)
//OR,
//May be you find better results if you do (m, n-1) and you end up
updating maxC with some LAAARGEST COMMON SUBSTRING LENGTH
int decrease_n = recur_memo(nums1, nums2, m, n-1); //stage (m, n-1)
//Like I said, you need to keep on finding the maxC in every call you
make throughout your journey.
maxC = max({maxC, max_substring_ending_here, decrease_m, decrease_n});
//BUT BUT BUT, you need to return the best you found at this stage (m, n)
return t[m][n] = max_substring_ending_here;
}
int findLength(vector<int>& nums1, vector<int>& nums2) {
int m = nums1.size();
int n = nums2.size();
memset(t, -1, sizeof(t));
recur_memo(nums1, nums2, m, n); //resurive+memoization
return maxC;
}
};
Link : https://leetcode.com/problems/maximum-length-of-repeated-subarray/discuss/1169215/(1)-Recursive%2BMemo-(2)-Bottom-Up-(C%2B%2B)
Here is a recursive and top-down approach:
public int lcsSubstr(char[] s1, char[] s2, int m, int n, int c) {
if (m == 0 || n == 0) {
return c;
}
if (s1[m-1] == s2[n-1]) {
c = lcsSubstr(s1, s2, m-1, n-1, c+1);
} else {
c2 = Math.max(lcsSubstr(s1, s2, m, n - 1, 0), lcsSubstr(s1, s2, m-1, n, 0));
}
return Math.max(c, c2);
}
public int lcsSubstrMemo(char[] s1, char[] s2, int m, int n, int c, int[][] t) {
if(m == 0 || n == 0) {
return c;
}
if (t[m-1][n-1] != -1) return t[m-1][n-1];
if(s1[m - 1] == s2[n - 1]) {
c = lcsSubstr(s1, s2, m - 1, n - 1, c + 1);
} else {
c2 = Math.max(lcsSubstr(s1, s2, m, n - 1, 0), lcsSubstr(s1, s2, m - 1, n, 0));
}
t[m - 1][n - 1] = Math.max(c, c2);
return t[m-1][n-1];
}
Memoization refers to caching the solutions to subproblems in order to use them later. In the longest common subsequence problem, you try to match substrings of two subsequences to see if they match, maintaining in memory the longest one yet found. Here is the solution in Java you are looking for (memoized version of LCS):
public class LongestCommonSubsequence {
private static HashMap<Container, Integer> cache = new HashMap<>();
private static int count=0, total=0;
public static void main(String sargs[]){
Scanner scanner = new Scanner(System.in);
String x=scanner.nextLine();
String y=scanner.nextLine();
int max=0;
String longest="";
for(int j=0;j<x.length();j++){
String common=commonSubsequence(j,0, x, y);
if(max<common.length()){
max=common.length();
longest=common;
}
}
for(int j=0;j<y.length();j++){
String common=commonSubsequence(j,0, y, x);
if(max<common.length()){
max=common.length();
longest=common;
}
}
System.out.println(longest);
System.out.println("cache used "+count+" / "+total);
}
public static String commonSubsequence(final int startPositionX, int startPositionY, String x, String y){
StringBuilder commonSubsequence= new StringBuilder();
for(int i=startPositionX;i<x.length();i++){
Integer index=find(x.charAt(i),startPositionY,y);
if(index!=null){
commonSubsequence.append(x.charAt(i));
if(index!=y.length()-1)
startPositionY=index+1;
else
break;
}
}
return commonSubsequence.toString();
}
public static Integer find(char query, int startIndex, String target){
Integer pos=cache.get(new Container(query, startIndex));
total++;
if(pos!=null){
count++;
return pos;
}else{
for(int i=startIndex;i<target.length();i++){
if(target.charAt(i)==query){
cache.put(new Container(query, startIndex), i);
return i;
}
}
return null;
}
}
}
class Container{
private Character toMatch;
private Integer indexToStartMatch;
public Container(char t, int i){
toMatch=t;
indexToStartMatch=i;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime
* result
+ ((indexToStartMatch == null) ? 0 : indexToStartMatch
.hashCode());
result = prime * result + ((toMatch == null) ? 0 : toMatch.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Container other = (Container) obj;
if (indexToStartMatch == null) {
if (other.indexToStartMatch != null)
return false;
} else if (!indexToStartMatch.equals(other.indexToStartMatch))
return false;
if (toMatch == null) {
if (other.toMatch != null)
return false;
} else if (!toMatch.equals(other.toMatch))
return false;
return true;
}
}

Power with divide & conquer algorithm

i want to find for calculating X^46, how many multiplication occurs with optimal D&C approach for calculating Power.
I think this is the best optimal code for calculating power with divide & conquer approach.
int power(int x, unsigned int y)
{
int temp;
if( y == 0)
return 1;
temp = power(x, y/2);
if (y%2 == 0)
return temp*temp;
else
return x*temp*temp;
}
in one note wrote for calculating X^46 with optimal Power code in D&C we need 8 multiplication, but in my code there is 10. anyone correct me?
Edit:
the last code is:
int power(int x, unsigned int y)
{
int temp;
if( y == 0)
return 1;
if( y ==1)
return x;
temp = power(x, y/2);
if (y%2 == 0)
return temp*temp;
else
return x*temp*temp;
}
You left out the optimizing base case of
if (y==1)
return x
and instead require extra multiplications from
temp = power(x, 0)
return x * temp * temp
The extra pair of multiplications come from the unnecessary final recursive call.
You have redundant multiplies due to not earlying out when y==1.
When y==1, you execute the last line:
return x*temp*temp;
which simplifies to:
return x*1*1;
Adding a special case for y==1 will get rid of the additional 2 multiplies.
int power(int x, unsigned int y)
{
int temp;
if( y ==1)
return x;
if (y%2 == 0){
temp = power(x, y/2);
return temp*temp;
}
else{
temp = power(x, (y-1)/2);
return x*temp*temp;
}
}
Best way to do it using the divide and conquer strategy. it will take O(log N) time to complete the execution. It will work for negative exponential also.
I'm doing this in C++:
#include <iostream>
using namespace std;
float power(int a, int b)
{
if (b == 0)
{
return 1;
}
else
{
float temp = power(a, b / 2);
if (b > 0)
{
if (b % 2 == 0)
{
return temp * temp;
}
else
{
return a * temp * temp;
}
}
else
{
return 1/power(a,-b);
}
}
}
int main()
{ int a , b ;
cout<<"Enter a Number:";cin>>a; cout<<"Enter its exponential:";cin>>b;
cout << power(a, b);
}
Output:
Output will be as follow

Resources