Print power of string/array - algorithm

Given an integer array nums of unique elements, return all possible subsets (the power set). The belwo code is returning wrong answer for input [1,2].How to fix it?
Expected Output is
[[],[1],[2],[1,2]]
I have written the code here which works fine.But i wanted to know why we are doing
https://leetcode.com/submissions/detail/735373452/
output.remove(output.size()-1);
But in the same code i don't do backtrack but it still print all power sets
String s = "ABC";
ps(s, 0, "");
public static void ps(String str, int i, String ans) {
if (i == str.length()) {
System.out.println(" Print " + ans);
return;
}
ps(str, i + 1, ans + str.charAt(i));
ps(str, i + 1, ans);
}

In short, you are creating 2 ^ n Strings during the recursive call, where n is the length of str. While the code in leetcode is using a single List. Adding elements to the List will have influence after the method call, thus need to remove the element to "restore" the List.
In Java, Strings are immutable. In your recursive ps function, you are creating new Strings with ans + str.charAt(i), the original ans remains the same. Therefore you don't need to use the backtracking.
// say ans == "A", and str.charAt(1) == "B":
ps(str, i + 1, ans + str.charAt(i));
ps(str, i + 1, ans);
// will be called as:
ps("ABC", 2, "AB");
ps("ABC", 2, "A");
In the leetcode code, it's using a List. All the recursive calls share the same List. Modifying the list will impact the following calls. If we add an element before calling the function, we need to remove the element after calling the function.
// ans is a List now, not String: ans == ['A', 'B']
ans.add(str.charAt(i)); // ans == ['A', 'B', 'C']
ps(str, i + 1, ans); // ps("ABC", 3, ['A', 'B', 'C'])
// ans is still ['A', 'B', 'C']
// we want to call ps("ABC", 3, ['A', 'B']) now:
ans.remove(ans.size() - 1);
ps(str, i + 1, ans);
Perhaps you are thinking that maybe changing the order will work:
ps(str, i + 1, ans);
ans.add(str.charAt(i));
ps(str, i + 1, ans);
It still has the problem if not calling ans.remove(str.charAt(ans.size() - 1). You can try changing the type of ans to List<Character> or StringBuilder in your ps function, and print ans during each recursive call.

Related

How legal is this operation in ruby? Appending a value directly to a function call

I have come across this recursive implementation of range using Ruby and I was trying to understand how we can append values straight into a recursive call? Can someone explain to me what is happening under the hood?
Here is the implementation:
def range(min, max)
return [] if max <= min
range(min, max - 1) << max - 1
end
The << operator is implemented as a method. This is actually syntactic sugar, so it's more like calling range(…).<<. This is just like method chaining, so the << method is actually being called on the return value of range, which appears to be an array. So it's calling Array#<<.
For what it's worth, this is an awful construct. Ruby doesn't do recursion well (unless you enable Tail Call Optimization), and it's hard to read. Much better to simply use the built in Range object:
some_range = 1..7
some_range_excluding_final_value = 1...7
# or if you really need an array:
(1..7).to_a
Can someone explain to me what is happening under the hood?
You can trace the recusion. If you call range(1, 4) the result will be range(1, 3) << 3. But in order to evaluate that, we need the result for range(1, 3) which is range(1, 2) << 2 and so on. If you write down each iteration you'll get:
range(1, 4)
range(1, 3) << 3
(range(1, 2) << 2) << 3
((range(1, 1) << 1) << 2) << 3
At this point, you have range(1, 1) which has a return value of [] because 1 <= 1 is true – the method's first line. The recursion ends and can finally be evaluated as:
(([] << 1) << 2) << 3
([1] << 2) << 3
[1, 2] << 3
[1, 2, 3]
When writing recursive methods, you often want to implement them in a tail-recursive way, because it can be optimized.
Tail-recursive means that your method's last expression is a call to itself, e.g.:
def range(min, max, result = [])
return result if max <= min
range(min, max - 1, result.unshift(max - 1))
end
Note that the last line merely invokes range again, just with different arguments. I had to add an extra argument result which stores the accumulated values and which eventually becomes the method's final result.
It would be evaluated as: (I've right-aligned it to make unshift more obvious)
range(1, 4, [])
range(1, 3, [3])
range(1, 2, [2, 3])
range(1, 1, [1, 2, 3])
[1, 2, 3]
Unfortunately, unshift is a rather expensive operation. It would be faster to push the values and then reverse the result:
def range(min, max, result = [])
return result.reverse if max <= min
range(min, max - 1, result.push(max - 1))
end
Step by step:
range(1, 4, [])
range(1, 3, [3])
range(1, 2, [3, 2])
range(1, 1, [3, 2, 1])
[1, 2, 3]
Or alternatively, push an incremented min instead of a decremented max which populates result in the correct order:
def range(min, max, result = [])
return result if max <= min
range(min + 1, max, result.push(min))
end
Which becomes:
range(1, 4, [])
range(2, 4, [1])
range(3, 4, [1, 2])
range(4, 4, [1, 2, 3])
[1, 2, 3]

Find vector of unique elements and vector of repeats using for loops and if conditions

I want a program that takes a vector of integers and creates two new vectors, one which contains each unique element, and another which contains the number of times these unique elements were repeated in the original vector.
So,
[1, 2, 2, 3, 3, 3]
has unique elements:
[1, 2, 3]
with the following number of repeats:
[1, 2, 3]
I know this has been asked before, but I want to achieve this using purely for loops and if conditions if need be. For the same reason, the code can be given in pseudocode obviously.
Please be nice, I am literally a beginner who learned programming syntax a few days ago.
Here a solution
var arr = [1, 2, 2, 2, 3, 3, 3, 3]
var unique = [...new Set(arr)]
var repeated = []
var i = 0
unique.map((a) => {
arr.map((b) => {
if(a === b) i++
})
repeated.push(i)
i = 0
})
console.log("[" + arr.join(",") + "] has unique elements [" + unique.join(",") + "] with the following number of repeats [" + repeated.join(",") + "]")

Collatz Chain Algorithm RUBY

I am trying to populate an array according to the Collatz sequence. The constraints for the sequence are as follows:
positive integers:
n → n/2 (n is even)
n → 3n + 1 (n is odd)
Example Output
3 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1
Ideally, I wanted to construct a recursive call that would populate the array according to the constraints of the sequence. However, I believe my logic for the recursive call is extremely flawed. The intended behavior is to iterate over the nested array, manipulating only the last element of each sub array until the element reaches 1. I am trying to build my understanding of recursion and would appreciate any suggestions on how to fix this problem.
def collatzSum(maxNumber)
sequenceHash = Hash.new(0)
i = maxNumber
until i == 0 do
if i.even?
sequenceHash[i] = [(i), (i / 2)]
elsif i.odd? && i != 1
sequenceHash[i] = [(i), (3 * i + 1)]
elsif i == 1
sequenceHash[i] = [i]
end
i -= 1
end
p sequenceHash
helper_method recursion. Method should take in hash values and iterate according to if statements.
=begin
desired output
hash = {5=>[5,16, 8, 4, 2,1],
4=>[4,2,1],
3=>[3,10,5,16,8,4,2,1],
2=>[2,1],
1=>[1]}
=end
Code:
collatzChain = lambda do |k|
j = 0
k = j[-1]
until k == 1 do
if k.even?
sequenceHash[k] << (k / 2)
elsif k.odd?
sequenceHash[k] << (3 * k + 1)
end
end
j += 1
end
collatzChain.call(sequenceHash.values)
sequenceHash
end
collatzSum(5)
So you mention that you wanted a recursive algorithm, your current approach looks iterative to me. To be recursive, you need to call the method you're in with values closer and closer to a base condition and then, once you hit the base condition, you return back out, up the call chain building up your return values. So, for the Collatz sequence a recursive approach would look like:
def build_collatz_chain(max_number)
return_value = [max_number]
# our base condition is when the number passed in is equal to 1, so
# when we get 1 as the max_number, we'll return an array looking like
# [1]
return return_value if max_number == 1
if max_number.even?
# here, with an even max_number, we'll recurse and call our method
# again, passing in the new max_number, which is the current
# max_number / 2.
return_value + build_collatz_chain(max_number / 2)
else
# same as above, but we're odd, so we'll recurse with 3 * max_number + 1
return_value + build_collatz_chain(3 * max_number + 1)
end
end
and now when we call this with a value of 5, what will end up happening is something like:
call build_collatz_chain(5)
call build_collatz_chain(16)
call build_collatz_chain(8)
call build_collatz_chain(4)
call build_collatz_chain(2)
call build_collatz_chain(1)
We have hit the base condition! return with [1]
return from 2 with [2, 1]
return from 4 with [4, 2, 1]
return from 8 with [8, 4, 2, 1]
return from 16 with [16, 8, 4, 2, 1]
return from 5 with [5, 16, 8, 4, 2, 1]
So, now if you want a hash of all numbers up to the passed in max_number with their Collatz chains as values you can use a helper to call this for each value, up to max (this helper is iterative, but could be made recursive...exercise for the viewer if you want it recursive):
def collatz_sum(max_number)
{ }.tap do |sequence_hash|
max_number.downto(1) do |i|
sequence_hash[i] = build_collatz_chain(i)
end
end
end
and then when you call collatz_sum(5) you get back:
{5=>[5, 16, 8, 4, 2, 1], 4=>[4, 2, 1], 3=>[3, 10, 5, 16, 8, 4, 2, 1], 2=>[2, 1], 1=>[1]}
The reason your approach is iterative is in the collatzChain lambda, you are setting a value (j) and then incrementing it and just looping through until k is equal to 1. It's also an infinite loop because you initially set k as:
j = 0
k = j[-1]
and so k == 0, and then you iterate until k == 1 and then you never update what the value of k is again.
It's not clear that a recursive operation is necessary here since this seems to be a straightforward mapping between a value x and f(x). By switching to a simple array output you can achieve what you want with:
def collatz_sum(max)
(2..max).map do |i|
[
i,
if (i.even?)
i / 2
else
3 * i + 1
end
]
end.reverse + [ [ 1 ] ]
end

backtracking n staircases at most k steps in a single jump

You need to climb a staircase that has n steps, and you decide to get some extra exercise by jumping up the steps. You can cover at most k steps in a single jump. Return all the possible sequences of jumps that you could take to climb the staircase, sorted.
My implementation is obviously giving me the wrong answer.
def climbingStaircase(n, k):
final_res=[]
final_res.append(CSR(n,k,[]))
return final_res
def CSR(n,k,res):
if n == 0:
return res
else:
for i in range(1,k+1):
if n-i>=0:
res.append(i)
n=n-i
res=CSR(n,i,res)
return res
For n = 4 and k = 2, the output should be
[[1, 1, 1, 1],
[1, 1, 2],
[1, 2, 1],
[2, 1, 1],
[2, 2]]
Actual output:
[[1,1,1,1,2,1]]
Can someone point out which part I'm missing?
One huge problem is in the code below: you deduct the quantity of steps for each possibility within the step range.
n=n-i
res=CSR(n,i,res)
When you're done exploring what you can do with a 1-step jump, you need to backtrack and try from the same starting point (this instance's original value of n) with a 2-step jump. Change the code to:
res = CSR(n-i, i, res)
This keeps the n value intact as you go through the loop.
In addition, you can't limit future jumps to the max of what you just took. Change that second parameter, too:
res = CSR(n-i, k, res)
That should get you moving. Also try this lovely debug blog for help. At least insert one or two tracing statements, such as
print n, k, res
at the top of your routine.
CAVEAT
This is not all of your trouble. The largest remaining problem is that CSR returns only one solution: every step you take is appended to the same list. You need a way to gather the completed solutions as separate lists; the append in climbingStaircase is executed only once, after CSR is entirely finished.
You need to recognize a completed solution at n==0.
DEBUGGING HELP
Here is a version of your program with the recursion parameters fixed, and debugging traces inserted.
indent = ""
def climbingStaircase(n, k):
final_res = []
final_res.append(CSR(n, k, []))
return final_res
def CSR(n, k, res):
global indent
indent += " "
print indent, n, k, res
if n == 0:
print "SOLUTION", res
else:
for i in range(1, k+1):
if n-i >= 0:
CSR(n-i, k, res + [i])
indent = indent[:-2]
print climbingStaircase(4, 2)
Note the use of "indent" to help visualize your recursion and backtracking. The critical part here is that, instead of updating res globally, I've left it as a local variable. I've also removed the return value for now, simply dumping to output the solutions as they're found. You can see how it works:
4 2 []
3 2 [1]
2 2 [1, 1]
1 2 [1, 1, 1]
0 2 [1, 1, 1, 1]
SOLUTION [1, 1, 1, 1]
0 2 [1, 1, 2]
SOLUTION [1, 1, 2]
1 2 [1, 2]
0 2 [1, 2, 1]
SOLUTION [1, 2, 1]
2 2 [2]
1 2 [2, 1]
0 2 [2, 1, 1]
SOLUTION [2, 1, 1]
0 2 [2, 2]
SOLUTION [2, 2]
[None]
With this stuff in place, I'm hopeful you can trace your logic and figure out how to capture the sequence of solutions at a level of your choosing.
Successfully implemented Prune's answer.
def climbingStaircase(n, k):
res=[]
CSR(n,k,[],res)
return res
def CSR(n,k,str_, res):
if n == 0:
res.append(str_)
else:
for i in range(1,k+1):
if n-i>=0:
CSR(n-i,k,str_+[i],res)
A quick Java version of this solution:
int[][] climbingStaircase(int n, int k) {
List<ArrayList<Integer>> list = new ArrayList<>();
climb(n, k, new ArrayList<Integer>(), list);
// convert to int[][]
int[][] result = new int[list.size()][];
for (int i=0; i<list.size(); i++) {
List<Integer> l = list.get(i);
int [] arr = new int[l.size()];
for (int j=0; j<l.size(); j++)
arr[j] = l.get(j);
result[i] = arr;
}
return result;
}
void climb(int n, int k, ArrayList<Integer> prev, List<ArrayList<Integer>> list) {
if (n==0) { // no more stairs, done climbing
list.add(prev);
} else {
for (int i=1; i<=k; i++) { // climb remaining stairs in intervals from 1 to k steps
if (i <= n) { // no need to test intervals larger than remaining # of stairs
ArrayList<Integer> branch = new ArrayList<>(prev);
branch.add(i);
climb(n-i, k, branch, list);
}
}
}
}
In Swift 5.5
func solution(n: Int, k: Int) -> [[Int]] {
var res_final = [[Int]]()
SRC(n: n, k: k, res: [], &res_final)
return res_final
}
var indent: String = ""
func SRC(n: Int, k: Int, res: [Int], _ res_final: inout [[Int]]) {
indent += " "
print(indent, n, k, res)
if n == .zero {
res_final.append(res)
print("Solution", res)
} else {
for i in 1...k {
if n-i >= .zero {
SRC(n: n-i, k: k, res: res + [i], &res_final)
}
}
}
indent = " "
}
solution(n: 4, k: 2)

How do you check if one array is a subsequence of another?

I'm looking to explore different algorithms, both recursive and dynamic programming, that checks if one arrayA is a subsequence of arrayB. For example,
arrayA = [1, 2, 3]
arrayB = [5, 6, 1, 7, 2, 9, 3]
thus, arrayA is indeed a subsequence of arrayB.
I've tried a few different searches, but all I can seem to find is algorithms to compute the longest increasing subsequence.
Since you must match all elements of arrayA to some elements of arrayB, you never need to backtrack. In other words, if there are two candidates in arrayB to match an element of arrayA, you can pick the earliest one, and never retract the choice.
Therefore, you do not need DP, because a straightforward linear greedy strategy will work:
bool isSubsequence(int[] arrayA, int[] arrayB) {
int startIndexB = 0;
foreach (int n in arrayA) {
int next = indexOf(arrayB, startIndexB , n);
if (next == NOT_FOUND) {
return false;
}
startIndexB = next+1;
}
return true;
}
As dasblinkenlight has correctly said(and i could not have phrased it better than his answer!!) a greedy approach works absolutely fine. You could use the following pseudocode (with just a little more explanation but totally similar to what dasblinkenlight has written)which is similar to the merging of two sorted arrays.
A = {..}
B = {..}
j = 0, k = 0
/*j and k are variables we use to traverse the arrays A and B respectively*/
for(j=0;j<A.size();){
/*We know that not all elements of A are present in B as we
have reached end of B and not all elements of A have been covered*/
if(k==B.size() && j<A.size()){
return false;
}
/*we increment the counters j and k both because we have found a match*/
else if(A[j]==B[k]){
j++,k++;
}
/*we increment k in the hope that next element may prove to be an element match*/
else if(A[j]!=B[k]){
k++;
}
}
return true; /*cause if we have reached this point of the code
we know that all elements of A are in B*/
Time Complexity is O(|A|+|B|) in the worst case, where |A| & |B| are the number of elements present in Arrays A and B respectively. Thus you get a linear complexity.
As #sergey mentioned earlier, there is no need to do backtracking in this case.
Here just another Python version to the problem: [Time complexity: O(n) - worst]
>>> A = [1, 2, 3]
>>> B = [5, 6, 1, 7, 8, 2, 4, 3]
>>> def is_subsequence(A, B):
it = iter(B)
return all(x in it for x in A)
>>> is_subsequence(A, B)
True
>>> is_subsequence([1, 3, 4], B)
False
>>>
Here is an example in Ruby:
def sub_seq?(a_, b_)
arr_a = [a_,b_].max_by(&:length);
arr_b = [a_,b_].min_by(&:length);
arr_a.select.with_index do |a, index|
arr_a.index(a) &&
arr_b.index(a) &&
arr_b.index(a) <= arr_a.index(a)
end == arr_b
end
arrayA = [1, 2, 3]
arrayB = [5, 6, 1, 7, 2, 9, 3]
puts sub_seq?(arrayA, arrayB).inspect #=> true
Here is an example in GOLANG...
func subsequence(first, second []int) bool {
k := 0
for i := 0; i < len(first); i++ {
j := k
for ; j < len(second); j++ {
if first[i] == second[j] {
k = j + 1
break
}
}
if j == len(second) {
return false
}
}
return true
}
func main(){
fmt.Println(subsequence([]int{1, 2, 3}, []int{5, 1, 3, 2, 4}))
}

Resources