LeetCode Day 28 Backtracking Algorithm (4/6)

3 minute read

Published:

Its over half way of backtracking!

Question 1

93. Restore IP Addresses

A valid IP address consists of exactly four integers separated by single dots. Each integer is between 0 and 255 (inclusive) and cannot have leading zeros.

  • For example, "0.1.2.201" and "192.168.1.1" are valid IP addresses, but "0.011.255.245", "192.168.1.312" and "192.168@1.1" are invalid IP addresses.

Given a string s containing only digits, return all possible valid IP addresses that can be formed by inserting dots into s. You are not allowed to reorder or remove any digits in s. You may return the valid IP addresses in any order.

It is still a segmentation type of problem, so the solution is recursive. The problem can still be thought of as a tree structure.

We need the variable startIndex because we can’t repeat the split and we need to keep track of where the next level of recursive splitting starts.

We also need the pointNum variable, which records the number of commas added, and is used to determine when the recursion ends.

We can use [startIndex, i] for loop to intercept the substring, and we need to determine whether the substring is legal.

class Solution:
    def restoreIpAddresses(self, s: str) -> List[str]:
        result = []
        self.backtracking(s, 0, 0, "", result)
        return result
 
    def backtracking(self, s, start_index, point_num, current, result):
        if point_num == 3:  
            if self.is_valid(s, start_index, len(s) - 1):  
                current += s[start_index:] 
                result.append(current)
            return
 
        for i in range(start_index, len(s)):
            if self.is_valid(s, start_index, i): 
                sub = s[start_index:i + 1]
                self.backtracking(s, i + 1, point_num + 1, current + sub + '.', result)
            else:
                break
 
    def is_valid(self, s, start, end):
        if start > end:
            return False
        if s[start] == '0' and start != end: 
            return False
        num = 0
        for i in range(start, end + 1):
            if not s[i].isdigit():  
                return False
            num = num * 10 + int(s[i])
            if num > 255:  
                return False
        return True

Question 2

78. Subsets

Given an integer array nums of unique elements, return all possible

subsets (the power set).

The solution set must not contain duplicate subsets. Return the solution in any order.

If the process of partitioning this problem, is abstracted to a tree, then what this problem needs is every node of this tree.

class Solution:
    def subsets(self, nums):
        result = []
        path = []
        self.backtracking(nums, 0, path, result)
        return result
 
    def backtracking(self, nums, startIndex, path, result):
        result.append(path[:])  
        for i in range(startIndex, len(nums)):
            path.append(nums[i])
            self.backtracking(nums, i + 1, path, result)
            path.pop()

Question 3

90. Subsets II

Given an integer array nums that may contain duplicates, return all possible

subsets (the power set).

The solution set must not contain duplicate subsets. Return the solution in any order.

The difference between this question and the previous one is that this one allows for duplicate elements, but the final resultant subset still needs to be de-weighted.

class Solution:
    def subsetsWithDup(self, nums):
        result = []
        path = []
        nums.sort() 
        self.backtracking(nums, 0, path, result)
        return result
 
    def backtracking(self, nums, startIndex, path, result):
        result.append(path[:])  
        uset = set()
        for i in range(startIndex, len(nums)):
            if nums[i] in uset:
                continue
            uset.add(nums[i])
            path.append(nums[i])
            self.backtracking(nums, i + 1, path, result)
            path.pop()