I am trying to write a very simple greedy algorithm for the knapsack problem. My inputs are two parallel arrays. One array contains the value of the item and the other array contains the weights.
The greedy algorithm that I’m trying to write would go as follows: check which item has the highest value and put this in the knapsack. Then set the value of this item to zero. Check again which item has the highest value and put it in the knapsack if the knapsack can still hold it. If it can hold it, set the value again to zero (after you’ve put it in) and start looking for the highest value again. If that knapsack cannot hold it anymore then just end the program.
I know that there are a lot of better greedy algorithms out there but this seems to me to be a pretty simple one and I think I could manage this. My problem is that I have to go through the entire values array to find the maximum value. Then when I’ve found it I put it in the knapsack and set the value to zero. But the problem then is that I have to go back in the for loop to find the new highest value item and put this in the knapsack. But I don’t know how I would go about doing this.
I am writing this in Java.
First of all, you usually solve Knapsack greedily by using the highest ratio value/weight instead of just the value.
Secondly, you do not need to search for the maximum in each step if you sort the list of items once and go through it step by step.
Related
I have read many variations of the Knapsack problem, but the version I am tasked with is a little different and I don't quite understand how to solve it.
I have an array of integers that represent weights (ie. {1,4,6,12,7,2}) and need to find only one solution that adds up to the target weight.
I understand the basic algorithm, but I cannot understand how to implement it.
First, what is my base case? Is it when the array is empty? The target has been reached? The target has been over-reached? Or maybe some combination?
Second, when the target is over-reached, how do I backtrack and try the next item?
Third, what am I supposed to return? Should I be returning ints (in which case, am I supposed to print them out?)? Or do I return arrays and the final return is the solution?
Think carefully about the problem you are trying to solve. To approach this problem, I am
considering the inputs and outputs of the Knapsack algorithm.
Input: A set of integers (the knapsack) and a single integer (the proposed sum)
Output: A set of integers who add up to the proposed sum, or null.
In this way your code might look like this
public int[] knapsackSolve(int[] sack, int prospectiveSum) {
//your algorithm here
}
The recursive algorithm is straightforward. First compute the sum of the sack. If it equals
prospectiveSum then return the sack. Otherwise iterate over sack, and for each item initialise a new knapsack with that item removed. Call knapsackSolve on this. If there is a solution, return it. Otherwise proceed to the next item.
For example if we call knapsackSolve({1,2,3},5) the algorithm tries 1 + 2 + 3 = 5 which is false. So it loops through {1,2,3} and calls knapsackSolve on the sublists {2,3},{1,3} and {1,2}. knapsackSolve({2,3},5) is the one that returns a solution.
This isn't a very efficient algorithm although it illustrates fairly well how complex the Knapsack problem is!
Basically the Knapsack problem is formulated as (from Wikipedia): "Given a set of items, each with a mass and a value, determine the number of each item to include in a collection so that the total weight is less than or equal to a given limit and the total value is as large as possible. For your problem we are interested in weights only. So you can set all values to 1. Additionally we only want to know if the target weight can be reached exactly. I guess you are allowed to use a weight only once and not multiple times?
This problem can be solved nicely with dynamic programming. Are you familiar with that principle? Applying dynamic programming is much more elegant and quicker to program than backtracking. But if you are only allowed to do backtracking use the approach from user2738608 posted above.
Is it possible to go through a boolean array to find a false value in O(logn) running time? The array's indices run from 0 to n-1.
If it is, how would we do it in java? Pseudo code is fine.
In general, the answer is "NO": you cannot go through an array in search of a single value in less than O(N), unless you know something about the order of array items.
For example, if the array is sorted, you can find the right spot in O(log N).
For boolean array being sorted means having all falses, if any, at the beginning, and all trues, if any, at the the end. If this is the case, you can use binary search to find the "demarcation point" in logarithmic time.
No. This is not possible without any further information about the array.
The best you can do is O(n), which is traversing the array from left to right and checking each item.
If the array is sorted you would need two checks, a false value could be on either end, which is O(1).
A common proof by contradiction:
Assume that the algorithm works correctly. Then, after inspecting less than all elements, the algorithm yields a correct answer. Now assume the algorithm has seen only trues, it yields an answer x. By now only changing values the algorithm has not inspected, I can always construct a test case in which the algorithm fails. Therefore, the algorithm must inspect all elements of an (unsorted) boolean array to determine if all are true.
Whatever you do, you will have to check all the values to ensure there is no false value. So linear time, with n/2 checks in average.
I'm look for the "how do you find it" because I have no idea how to approach finding the algorithm complexity of my program.
I wrote a sudoku solver using java, without efficiency in mind (I wanted to try to make it work recursively, which i succeeded with!)
Some background:
my strategy employs backtracking to determine, for a given Sudoku puzzle, whether the puzzle only has one unique solution or not. So i basically read in a given puzzle, and solve it. Once i found one solution, i'm not necessarily done, need to continue to explore for further solutions. At the end, one of three possible outcomes happens: the puzzle is not solvable at all, the puzzle has a unique solution, or the puzzle has multiple solutions.
My program reads in the puzzle coordinates from a file that has one line for each given digit, consisting of the row, column, and digit. By my own convention, the upper left square of 7 is written as 007.
Implementation:
I load the values in, from the file, and stored them in a 2-D array
I go down the array until i find a Blank (unfilled value), and set it to 1. And check for any conflicts (whether the value i entered is valid or not).
If yes, I move onto the next value.
If no, I increment the value by 1, until I find a digit that works, or if none of them work (1 through 9), I go back 1 step to the last value that I adjusted and I increment that one (using recursion).
I am done solving when all 81 elements have been filled, without conflicts.
If any solutions are found, I print them to the terminal.
Otherwise, if I try to "go back one step" on the FIRST element that I initially modified, it means that there were no solutions.
How can my programs algorithm complexity? I thought it might be linear [ O(n) ], but I am accessing the array multiple times, so i'm not sure :(
Any help is appreciated
O(n ^ m) where n is the number of possibilities for each square (i.e., 9 in classic Sudoku) and m is the number of spaces that are blank.
This can be seen by working backwards from only a single blank. If there is only one blank, then you have n possibilities that you must work through in the worst case. If there are two blanks, then you must work through n possibilities for the first blank and n possibilities for the second blank for each of the possibilities for the first blank. If there are three blanks, then you must work through n possibilities for the first blank. Each of those possibilities will yield a puzzle with two blanks that has n^2 possibilities.
This algorithm performs a depth-first search through the possible solutions. Each level of the graph represents the choices for a single square. The depth of the graph is the number of squares that need to be filled. With a branching factor of n and a depth of m, finding a solution in the graph has a worst-case performance of O(n ^ m).
In many Sudokus, there will be a few numbers that can be placed directly with a bit of thought. By placing a number in the first empty cell, you give up on a lot of opportunities to reduce the possibilities. If the first ten empty cells have lots of possibilities, you get exponential growth. I'd ask the questions:
Where in the first line can the number 1 go?
Where in the first line can the number 2 go?
...
Where in the last line can the number 9 go?
Same but with nine columns?
Same but with the nine boxes?
Which number can go into the first cell?
Which number can go into the 81st cell?
That's 324 questions. If any question has exactly one answer, you pick that answer. If any question has no answer at all, you backtrack. If every question has two or more answers, you pick a question with the minimal number of answers.
You may get exponential growth, but only for problems that are really hard.
I'm trying to implement radix sort that sorts 50000 integers using a queue.
I have two idea in my mind for the base condition and I'm not sure it will work.
Get the biggest value in the array to determine how many times we need to go through the 10th, 100th, 1000th space.
Put number in the appropriate bin queue until all numbers have 0 at the front then return the integer in the bin back to the array?
Please let me know if there is a better way
take a look at this : www.math.ucla.edu/~tat/MicroTeach/radixsort.ppt
Given a sorted list of strings and the last entry is null. You cannot use the list.length to determine the length of the list, but come with an approach efficient than O(n) to find the end Index of list or length of list?
Fast and dirty, but it should get things done.
This is just like a guess a number scenario. Start with an arbitrarily large number.
While key exists, double. Once IndexOutOfBounds is thrown, continue to step two.
Does that index exist?
Yes, then halve the difference between the next know number above the current index and add to the current index.
No? Then halve the difference between the next know number below the current index and the current one.
The good news? This is O(logn). The bad news? You have a potential of having logn/2 exceptions.
Sounds like homework.
Look at List.iterator() and the Iterator interface.
Using a binary search will give you O(logn)
So just search for the null entry :)
Easy: Use the 'List.size()' method. The Java 'List' interface does not have a "length" field or property.
;->