简体   繁体   中英

Confused about Backtracking?

I'm trying to solve this Leetcode Question but I'm getting an error where I'm exceeding the time limit.

class Solution:  

def readBinaryWatchHelper(self,hours, minutes, num, pastHours, pastMinutes):
    if num == 0:
        hour, minute = sum(pastHours), sum(pastMinutes)
        if self.isValidTime(hour, minute):
            time = str(hour) + ":" + str(minute).zfill(2)
            self.times.add(time)
    else:
        for i in minutes:
            cMinutesTemp = list(minutes)
            pMinutesTemp = list(pastMinutes)
            pMinutesTemp.append(i)
            cMinutesTemp.remove(i)
            if self.isValidTime(sum(pastHours), sum(pMinutesTemp)):
                self.readBinaryWatchHelper(hours, cMinutesTemp, num - 1, pastHours, pMinutesTemp)    
        for i in hours:
            cHoursTemp = list(hours)
            pHoursTemp = list(pastHours)
            pHoursTemp.append(i)
            cHoursTemp.remove(i)
            if self.isValidTime(sum(pHoursTemp), sum(pastMinutes)):
                self.readBinaryWatchHelper(cHoursTemp, minutes, num - 1, pHoursTemp, pastMinutes)


@staticmethod
def isValidTime(hours, minutes):
    if hours < 12 and minutes < 60:
        return True
    return False

def readBinaryWatch(self, num):
    self.times = set()
    hChoices = [1,2,4,8]
    mChoices = [1,2,4,8,16,32]
    self.readBinaryWatchHelper(hChoices[::-1], mChoices[::-1], num, [],[])
    return list(self.times)

That's the solution I've written up using Backtracking. I was hoping I could get feedback on why it's too slow? One of the valid solutions is just getting all the combinations of hours from 0 - 12 and minutes from 0 - 60 and checking the sum of the bits to see if they add up to the correct sum. I'm confused as to how that solution is faster than mine? Shouldn't mine be faster due to the "tree pruning"? Thanks guys.

A solution w/o backtracking but using itertools and list comp would be:

class Solution:
    def readBinaryWatch(self, num):
        """
        :type num: int
        :rtype: List[str]
        """
        from itertools import combinations,  product
        hhmin = min(num,3)+1 # only generate at much as needed
        mmmin = min(num,5)+1 # only generate as much as needed
        nBits = [1,2,4,8,16,32]

        # {0: ['0'], 1: ['1','2','4','8'], 2: ['3','5','9','6','10'], 3: ['7','11']} for>2 
        h = { bitCount: list(str(sum(x)) for x in combinations(nBits,bitCount) 
                          if sum(x) < 12) for bitCount in range(hhmin)}

        m = { bitCount: list(str(sum(x)).zfill(2) for x in combinations(nBits,bitCount) 
                          if sum(x) < 60) for bitCount in range(mmmin)}

        ranges = ((h[subl[0]],m[subl[1]]) for subl in (x for x in product(range(num + 1),
                          range(num + 1)) if sum(x) == num and x[0]<hhmin and x[1]<mmmin))

        return ["{0}:{1}".format(hh,mm) for (hhhh,mmmm) in ranges 
                                        for hh in hhhh for mm in mmmm]

Test with:

s = Solution()
for n in range(8):
    print(s.readBinaryWatch(n))
    print() 

It dials in between 55ms and 64ms depending on whatever between different submits. According to the page this reaches 77% - there are some much shorter and more elegnant solutions. You can inspect some of them once you submit one. Yours unfortunately does not run at all, recursion needs recursive which seems to be too slow.

Funny enough the "brute force" if.. elif .. elif ... else with prefabbed lists is below 50% - just had to try it ;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM