# Leetcode 2021 annual brush questions by type summary backtracking method (python)

Posted by zeno on Fri, 11 Feb 2022 07:13:06 +0100

## Example 1: 77 combination

77. Portfolio
This question is mainly to understand the basic use of backtracking algorithm. Take the given n=4,k=2 as an example

(source: Code Capriccio)

As can be seen from the above figure, the logic of the code is to insert for loop traversal in recursion. The exit condition of a recursive loop is when the path length reaches k. However, there are some small errors in the coding process, such as my first version of the code:

### Wrong version

```class Solution(object):
def combine(self, n, k):
"""
:type n: int
:type k: int
:rtype: List[List[int]]
"""
res=[]
path=[]
def dfs(n,k,indx):
if len(path)==k:
res.append(path)
return
for i in range(indx,n):
path.append(i)
dfs(n,k,i+1)
path.pop()

dfs(n,k,1)
return res
```

The first problem is that res.append(path) is a shallow copy of path. Res will change every time the path changes, so the final res is an empty array. The correct writing should be res.append(path [:]);
In this way, the number "for" in "is not correct. The reason why it is written as for i in range(indx,n):, is because I'm a little confused about what dfs(n,k,n+1) will get in the for loop. Think carefully about the situation if len(path)==k is not satisfied. At this time, because indx is n+1 and can't enter the for loop, dfs(n,k,n+1) will jump naturally.

### Correct version:

```class Solution(object):
def combine(self, n, k):
"""
:type n: int
:type k: int
:rtype: List[List[int]]
"""
res=[]
path=[]
def dfs(n,k,indx):
if len(path)==k:
res.append(path[:])
return
for i in range(indx,n+1):
path.append(i)
dfs(n,k,i+1)
path.pop()

dfs(n,k,1)
return res
```

There is still room for optimization in the above code. For example, for the case of n = 4 and K = 4, only [1,2,3,4] meets the requirements. Other cases with 2, 3 and 4 as the starting position are not enough for the number of elements we need, so there is no need to search. In this case, pruning method can be used to optimize.

```	Assume the number of elements that have been selected: len(path),Then the number of elements needed is: k - len(path). Then in the collection n At most from this starting position : n - (k - len(path)) + 1 Start traversal from greater than n - (k - len(path)) + 1 The number of elements will be insufficient at the beginning of traversal, so there is no need to traverse
```

(more detailed description: Code Capriccio)

### Pruning optimized version:

Note here that n - (k - len(path)) + 1 is taken, so it is written as n - (k - len(path)) + 2;
It can be found that the execution time is greatly reduced

```class Solution(object):
def combine(self, n, k):
"""
:type n: int
:type k: int
:rtype: List[List[int]]
"""
res=[]
path=[]
def dfs(n,k,indx):
if len(path)==k:
res.append(path[:])
return
for i in range(indx,n - (k - len(path)) + 2):
path.append(i)
dfs(n,k,i+1)
path.pop()

dfs(n,k,1)
return res
```

## Example 2: 306 Cumulative addend

This question is the same logic as the previous one, but it's more mental than the previous one.
First, there are three steps:

##### 1, Variables to be determined.

num must be required; index used to point to the current number;
The number is currently the count of the feasible number (only count > = 2 meets the condition of cumulative number);
It also refers to prevprev of the previous number and prev of the previous number, as well as the current number being determined

##### 2, Single layer logic

First assume that the current number current is 0, I get len(num) from the index pointing to the current number, turn num[i] into int, and try to attach it to current, current=current*10+int(num[i]). When the effective number is greater than or equal to two, that is, when count > = 2, if the current current < (prevprev + prev), it indicates that the current number is not large enough, and it may be necessary to get the next number, so continue the cycle; If current > (prevprev + prev), it indicates that the current number is unqualified and directly returns false.
When count < 2 or current==(prevprev+prev), you need to judge if dfs(num,i+1,count+1,prev,current)
Take "199100" as an example. If count < 2, first treat the initial number "1" as an independent number, and then treat the subsequent "9" as an independent number. prevprev=1,prev=9,current=9. At this time, current > (prevprev + prev), so return False, that is, dfs(num,2,2,9,9) is False, the for loop continues, current becomes 99, and continues down
current==(prevprev+prev), continue to search

##### 3, Conditions for exiting recursion

When index > = len (Num) and count > 2, it indicates that you can exit normally and return True
If index > = len (Num) is reached, and the valid number is not greater than 2, return false (such as "19910")

```class Solution(object):
"""
:type num: str
:rtype: bool
"""

n=len(num)
# if n<3:
#     return False

def dfs(num,index,count,prevprev,prev):
if index>=len(num):
if count>2:
return True
else:
return False
# return count>2

current=0
for i in range(index,len(num)):
c=num[i]
if num[index]=='0' and i>index:
return False

current=current*10+int(c)

if count>=2:
if current>(prevprev+prev):
return False
if current<(prevprev+prev):
continue

if dfs(num,i+1,count+1,prev,current):
return True

return False

return dfs(num,0,0,0,0)
```

Topics: Python leetcode