solving knapsack dynamic programming debugging - algorithm

I tried to solve the classical knapsap problem myself. But I am getting a wrong answer as 108. Could you help me to figure out what I have done wrong. Here I am using recursion.
Weight limit is 10
answer is 5+3+2 ==> 25+15+14=54
public class KnapSack {
public static int[] weight={6,5,4,3,2};
public static int[] value={12,25,24,15,14};
public static void main(String[] args) {
System.out.println(c(0,0,10));
}
public static int c(int currentElement,int currentValue,int currentReamainder){
int p = 0;
if(currentReamainder<=0) return currentValue;
for(int i=currentElement;i<weight.length;i++){
if(currentReamainder<weight[i]) return currentValue;
p = Math.max(value[i]+c(i+1,currentValue+value[i],currentReamainder-weight[i]),c(i+1,currentValue,currentReamainder))
}
return p;
}
}
Update:
What should I do to print the weights of the optimum solution ?

Your error is this line
p=Math.max(value[i]+c(i+1,currentValue+value[i],currentReamainder-weight[i]),c(i+1,currentValue,currentReamainder));
it should be
int val = Math.max(value[i]+c(i+1,currentValue+value[i],currentReamainder-weight[i]),c(i+1,currentValue,currentReamainder));
p = Math.max(val, p);
The last bug is when you both updating currentValue and return p at the same time, so imagine the last call, when the function return currentValue, plus the last value[i] in each step, so your result is double
So , your function should be (notice I have removed the currentValue parameter, which is not necessary):
public static int c(int currentElement,int currentReamainder){
int p = 0;
if(currentReamainder<=0) return 0;
for(int i=currentElement;i<weight.length;i++){
if(currentReamainder<weight[i]) break;//This line is not valid, only when the weight array is sorted(ascending order)
int val = Math.max(value[i]+c(i+1,currentReamainder-weight[i]),c(i+1,currentReamainder));
p = Math.max(val, p);
}
return p;
}

Related

Big O of union method of dynamic connectivity problem

i faced a paradox to analyse this function, Why the time complexity of this function is N^2 and not N?
public void union(int a, int b) {
int aid = ids[a];
int bid = ids[b];
for (int i = 0; i < ids.length; i++) {
if (ids[i] == aid) {
ids[i] = bid;
}
}
}
Its an implementation of eager approach, to solve dynamic connectivity problem , complete code is:
// Union method has N^2 time complexity!!
class EagerApproach extends UnionFind {
protected int[] ids;
EagerApproach(int[] input) {
super(input);
ids = new int[input.length];
System.arraycopy(input, 0, ids, 0, input.length);
}
public boolean connected(int a, int b) {
return ids[a] == ids[b];
}
public void union(int a, int b) {
int aid = ids[a];
int bid = ids[b];
for (int i = 0; i < ids.length; i++) {
if (ids[i] == aid) {
ids[i] = bid;
}
}
}
public int[] getIds() {
return ids;
}
}
Provided your array access ids[x] is in constant time O(1), the time complexity of the union method is linear in the length of the array ids. So
O(ids.length)
or O(n) if we define n as ids.length.
Be careful with the definition of n and ids though. If, in your specific application, n was defined as ids.length = n * n, then this is obviously O(n^2) with n being sqrt(ids.length).

Path exists between cities or not

The link to the problem is Q4 Traveling is Fun.
I can only think of a brute force approach to compute every possible gcd and run bfs from source to destination to check if there exists a path or not.
But the above approach gives TLE in 5 test cases.
Can anyone provide a more efficient approach ?
This is a quick implementation of the graph structure I would use:
class GCDGraph {
private Map<Integer, Set<Integer>> adj = new HashMap<>();
public GCDGraph(int g, int[] srcCities, int[] dstCities){
int n = srcCities.length;
for(int i=0;i<n;i++){
adj.put(i, new HashSet<>());
}
for(int i=0;i<n;i++){
for(int j=0;j<i;j++){
int gtmp = gcd(srcCities[i], dstCities[j]);
if(gtmp > g){
adj.get(i).add(j);
adj.get(j).add(i);
}
}
// we could add the connection i -> i (assuming srcCities[i] > g)
// but that would not help us find a path, as it introduces a cycle
}
}
private int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }
public Set<Integer> adjacentVertices(int vertex){ return adj.get(vertex); }
public int size(){ return adj.size(); }
public boolean isEmpty(){ return size() == 0; }
public boolean hasPath(int src, int dst){
return buildPath(src, dst, new HashSet<>());
}
private boolean buildPath(int src, int dst, Set<Integer> tmp){
if(src == dst){
return true;
} else {
for(int nextVertex : adjacentVertices(src)){
if(tmp.contains(nextVertex))
continue;
tmp.add(nextVertex);
if(buildPath(nextVertex, dst, tmp))
return true;
tmp.remove(nextVertex);
}
}
return false;
}
}
It explicitly stores the adjacency as a Map (allowing fast lookup).
It has some utility methods (size, isEmpty).
It only looks up the GCD when it is being built, and only once for each x/y pair.
And it uses recursion to perform BFS, quitting as soon as possible.

Time and space complexity of if(!areAllArrayElementsZero())

How can I calculate the time and space complexity of a program(pseudo code) as follows:
function(){
if(!areAllArrayElementsZero()){
if(hasAnyOdd()){
decreaseOneFromFirstOddElementInArray()
} else {
divideAllArrayElementByTwo()
}
}
}
Here areAllArrayElementsZero(),hasAnyOdd(),divideAllArrayElementByTwo() has the complexity O(n). Any leads would help. Actually I was designing the solution to this problem.
Here is the Java equivalent of the above pseudo code, I've designed:
package competitive;
/*
* Problem: http://www.geeksforgeeks.org/count-minimum-steps-get-given-desired-array/
*/
class formarray{
private static int[] elem;
private static boolean areAllZeros(){
for(int i=0; i<elem.length;i++){
if(elem[i]>0){
return false;
}
}
return true;
}
private static boolean hasAnyOdd(){
for(int i=0; i<elem.length;i++){
if(elem[i]%2 != 0){
// odd element discovered
return true;
}
}
return false;
}
private static boolean decreaseFirstOddByOne(){
for(int i=0; i<elem.length;i++){
if(elem[i]%2 != 0) {
// odd element discovered
elem[i]-=1;
// return true if one is decreased from first odd element
return true;
}
}
return false;
}
private static void DivideArrayElementsByTwo(){
for(int i=0; i<elem.length;i++){
// we are not checking element to be even as it has already been checked
elem[i] = elem[i]/2;
}
}
public static void main(String args[]){
elem = new int[args.length];
// assign values
for(int i=0;i<args.length;i++){
elem[i] = Integer.parseInt(args[i]);
}
int steps=0;
while(!areAllZeros()){
if(hasAnyOdd()){
// the array has odd members
if(decreaseFirstOddByOne()){
steps++;
}
} else {
DivideArrayElementsByTwo();
steps++;
}
}
System.out.println("Total steps required: "+steps);
}
}
There are exactly 4 paths of execution; sum up the cost of each, take the largest.
Or realize there are no loops and each path has a finite number of O(n) elements, making the whole thing O(n).

Need help on Rod Cutting with Memoization

I had implelmented the rod cutting using memoization technique in java and here is the code that i have come up so far:
public class RodCutMemo {
public static int [] memo;
public static void main(String args [])
{ int [] prices = {0,2,3,5,8,6,4,9,10,12,15,16,17,18,20,22,31,50} ;
int n=5;
memo = new int [n+1];
for(int i =1;i<=n;i++)
{ memo[i]=-9999;}
System.out.println(maxProfitRodCutMemo(prices ,n));
}
public static int maxProfitRodCutMemo(int [] prices,int n)
{ if(memo[n]>=0)
{
return memo[n];}
//else if(n==0)
//{
// return 0;
//}
else
{ int q = -9999;
for(int i =1;i<=n;i++)
{q=Math.max(q,prices[i]+maxProfitRodCutMemo(prices, n-i) );}
return q;}}}
I have two questions here...
Q1)I have commented out one of the base conditions..if(n==0).Is that required in code.Am i missing some corner case without that??
Yes!
The simple answer to your question comes out when you consider i=n(in the for loop in the function maxProfitRodCutMemo), which will lead to calling of maxProfitRodCutMemo(int [] prices,0), which wont give you a correct result
according to your code (as you dont have any condition to check it)..

A more effective algorithm

This is my first time posting question, do pardon me if anything I do is wrong.
My question here is how to get a faster algorithm from this code? i'm currently using 2 stacks to implement the code such that it will get the minimum value out of the range of index User asks for input.
Example (2,3,4,5,1), if (user selects (1,4)), it means they are looking at (2,3,4,5), which the output is 2.
Thanks.
import java.util.*;
interface StackADT <Integer> {
// check whether stack is empty
public boolean empty();
// retrieve topmost item on stack
public int peek() throws EmptyStackException;
// remove and return topmost item on stack
public int pop() throws EmptyStackException;
// insert item onto stack
public void push(int item);
}
class StackArr <Integer> implements StackADT <Integer> {
private int[] arr;
private int top;
private int maxSize;
private final int INITSIZE = 1000;
public StackArr() {
arr = (int[]) new int[INITSIZE]; // creating array of type E
top = -1; // empty stack - thus, top is not on an valid array element
maxSize = INITSIZE;
}
public boolean empty() {
return (top < 0);
}
public int peek() throws EmptyStackException {
if (!empty()) return arr[top];
else throw new EmptyStackException();
}
public int pop() throws EmptyStackException {
int obj = peek();
top--;
return obj;
}
public void push(int obj) {
if (top >= maxSize - 1) enlargeArr();
top++;
arr[top] = obj;
}
}
class RMQ{
//declare stack object
Stack<Integer> stack1;
public RMQ(){
stack1 = new Stack<Integer>();
}
public void insertInt(int num){
stack1.push(num);
}
public int findIndex(int c, int d){
Stack<Integer> tempStack = new Stack<Integer>();
Stack<Integer> popStack = new Stack<Integer>();
tempStack = (Stack)stack1.clone();
while (d != tempStack.size())
{
tempStack.pop();
}
int minValue = tempStack.pop();
popStack.push(minValue);
while (c <= tempStack.size())
{
int tempValue = tempStack.pop();
if(tempValue >= minValue)
{
continue;
}
else
{
popStack.push(tempValue);
minValue = tempValue;
}
}
return popStack.pop();
}
}
public class Pseudo{
public static void main(String[] args){
//declare variables
int inputNum;
int numOfOperations;
//create object
RMQ rmq = new RMQ();
Scanner sc = new Scanner(System.in);
//read input
inputNum = sc.nextInt();
//add integers into stack
for(int i=0; i < inputNum; i++){
rmq.insertInt(sc.nextInt());
}
// read input for number of queries
numOfOperations = sc.nextInt();
// Output queries
for(int k=0; k < numOfOperations; k++){
int output = rmq.findIndex(sc.nextInt(), sc.nextInt());
System.out.println(output);
}
}
}
Why are you using a stack? Simply use an array:
int[] myArray = new int[inputNum];
// fill the array...
// get the minimum between "from" and "to"
int minimum = Integer.MAX_VALUE;
for(int i = from ; i <= to ; ++i) {
minimum = Math.min(minimum, myArray[i])
}
And that's it!
The way I understand your question is that you want to do some preprocessing on a fixed array that then makes your find min operation of a range of elements very fast.
This answer describes an approach that does O(nlogn) preprocessing work, followed by O(1) work for each query.
Preprocessing O(nlogn)
The idea is to prepare a 2d array SMALL[a,k] where SMALL[a,k] is the minimum of the 2^k elements starting at a
You can compute this array in a recursive way by starting at k==0 and then building up the value for each higher element by combining two previous elements together.
SMALL[a,k] = min(SMALL[a,k-1] , SMALL[a+2^(k-1),k-1])
Lookup O(1) per query
You are then able to instantly find the min for any range by combining 2 preprepared answers.
Suppose you want to find the min for elements from 100 to 133. You already know the min of 32 elements 100 to 131 (in BIG[100,5]) and also the min of 32 elements from 102 to 133 (in BIG[102,5]) so you can find the smallest of these to get the answer.
This is Range Minimum Query problem.
There are some algorthms and data structures to solve it effectively

Resources