Need help on Rod Cutting with Memoization - algorithm

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

Related

time complexity, Java

Please see the code that I wrote based on a school example.
public class Test {
public static void main(String [] args)
{
int number = 0;
int [] array = new int[number+1];
array[number] = 0;
methodName(number, array);
}
public static void methodName(int n, int[] b )
{
if (n == 0)
{
System.out.println(" b is : " + b);
return;
}
else
{
b[n-1] = 0;
methodName(n-1, b);
b[n-1] = 1;
methodName(n-1, b);
}
}
}
I am trying to calculate the best and worst case time complexity of this code.
As far as I understand the best case would be O(1).
And I'm having a difficulty determining the worst case.
There are four basic operations in the else loop.
I know that this is a progressively growing function and I have a feeling it is close to being O(!n).
Thank you for your time.
IF methodName is not getting called from anywhere else than main,
then it would always be O(1)

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.

solving knapsack dynamic programming debugging

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;
}

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

Creat a main method to a quickSort class

This is my code so far. I need help to implement a main method that reads and sorts the supplied test files(unsorted1.txt and unsorted2.txt)
public class quickSort extends DLList {
public static <E extends Comparable <? super E>> void quickSort(DLList<E> element){
sort(element, 0, element.size() - 1);
}
public static <E extends Comparable <? super E>> void sort(DLList<E> element, int l, int r) {
int i = l;
int j = r;
E pivot = element.get((l + r) / 2), w;
do {
while (element.get(i).compareTo(pivot)< 0){
++i;
}
while (element.get(j).compareTo(pivot)> 0){
--j;
}
while (i <= j) {
w = element.get(i);
element.set(i, element.get(j));
element.set(j, w);
++i;
--j;
}
} while (i <= j);
if (l < j) {
sort(element, l, j);
}
if (i < r) {
sort(element, i, r);
}
}
public static void main(String[] args){
}
My quicksort implementation is complete and it is based on a doubly linked list.
The text files contain a number of unsorted characters. So I have to load all characters and store them in the list.
And that's what I need help with.
Can you please elaborate a little more on files part?
What is the data format in the file? Should the output format after sorting be the same as input format?
As much as i understand your quicksort implementation is ready, all that you need is to parse the text file and sort and write it back to the file.

Resources