diff --git a/CombinationSum.py b/CombinationSum.py new file mode 100644 index 00000000..154f65fb --- /dev/null +++ b/CombinationSum.py @@ -0,0 +1,51 @@ +class Solution(object): + # tc : O(2*hm) each time we check choosign or not choosing so 2 power and h is the target/nums[i] so each node the hieght is until the target is formed and 2*h is for every m elements in the inoput arr + # sc : O(n) every element is explored with taking and not taking at one point we keep on gng (not taking path) til the n elemenst so at worst case at one time we can have n space in the recrussive stack. + def combinationSum(self, candidates, target): + """ + :type candidates: List[int] + :type target: int + :rtype: List[List[int]] + """ + # intution + # trick parts are : to know how many times a number can be taken and which number to skip tp form the target + # to solve this, we have to exhaustielvy check taking each number x times or not take and keep checking the sum of the numbers is target or not + # will use recurssion and at every time recurssively check by choosing the number nd not choosing ith number and following the same pattern for the i+1th number as well until we check all the possibilities of each number which can give the target + # to stop the recurssive condition once if the target-nums[i] turns negative then its no more a viable path we will stop from exhaustlievly checking that path and go back one step ahead and recursively check the parent path + + self.result = [] + idx = 0 + path = [] + self.helper(candidates,idx,target,path) + + return self.result + + # will have a helper function where we will start form a index and then iterativekly check the combinations of the paths possible from index to the end of the arr list once we foudn the possibel paths with index we will move + # our index one step as we already explored the paths possibel with the index, now we will check the paths possibel with the next element in the arr + def helper(self,candidates,idx,target,path): + # base condition + if target < 0 or idx > len(candidates)-1 : #check if idx is out of bounds + return + + # valid path found + if target == 0: + self.result.append(list(path)) # since the path will be override everytime the final output will be the final path in the recursive function rather than the valid paths we found in recurssion, hence will create a deep copy while adding in the final output + return + + # not choosing the element moving piviot one step + self.helper(candidates,idx+1,target,path) # everyting remains the same we move the index and check possibilitis with the next element + + # action + # choosing this element which reduces th target and also we can chose the same element again so will continue from idx itself, out helper function will take care tocheck possibilitie sof taking this number and also skipping the number + path.append(candidates[idx]) + + # recruse + self.helper(candidates,idx,target-candidates[idx],path)# path will have the choosen element in it + + # backtrack + path.pop() # once we are done of both choosing and not choosing of an element then we have to pop it up before it goes back tot he parent path to explore if not we will have all the elemenst explored in the path which is wrong + + + + + diff --git a/Expressions.py b/Expressions.py new file mode 100644 index 00000000..a79969d0 --- /dev/null +++ b/Expressions.py @@ -0,0 +1,61 @@ +class Solution(object): + # tc : O(n*4^n) at each step we have 4 calls: not choosing, and 3 operations and the depth of tree is n so 4^n calls, and curr making a substring n times + # sc : O(n^2) , recrussion stack take n space and at each node we do cur which is substrign from pivot to i+1 which is n^2 complexity + def addOperators(self, num, target): + """ + :type num: str + :type target: int + :rtype: List[str] + """ + # intution + # need to check possibilities of taking the combination of numbers and also with combination of operations like 12*3, + #1*2*3 etc etc, approach : will do 0/1 recurssion i.e 0 is not gng to process this element by itself( like use 12 instead of 1 itself) + # 1 as choosign in choosing have to do 3 perations +,-,* + # once we have done all procesing all the elements in the nm and if this combination of expression gives the target then we append the path ( where path is the exression of the nums) + + self.result = [] + self.helper(num,target,0,0,0,"") + + return self.result + + # will use cal, tail such that we can know the change done in the previous stage and in case of +,- we can simply + # do cal+nums[i] or cal - nums[i] but in case of * we have to priotize * over +,- so we find the change which is the number before * and then we will process the expression as + # (cal- tail) + (tail*curr) + + def helper(self,num,target,pivot,cal,tail,expression): + + # base + if pivot == len(num) and cal == target: + self.result.append(expression) + return + + + for i in range(pivot,len(num)): + + # if the num[i] is 0, our expression should not return with leading zeros + # 1 + 0 +5 is fine but 1 + 05 is not so when the pivot is 0 and out i > pivot mena sour curr start value is gng to be 0 follwoed by some number at this case we will simply do ntg + if num[pivot] == '0' and i > pivot: + break + + curr = int(num[pivot:i+1]) + + if pivot == 0: + self.helper(num,target,i+1, curr,curr,expression + str(curr)) # movign 1 step and we didnt choose so no chaneg in cal, tail + else: + + # + + self.helper(num,target,i+1,cal + curr, curr, expression + "+" + str(curr)) + + # - + self.helper(num,target,i+1,cal - curr, -curr, expression + "-" + str(curr)) + + # * + self.helper(num,target,i+1,(cal- tail) + (tail*curr), tail* curr, expression + "*" + str(curr)) + + + return + + + + + \ No newline at end of file