Backtracking is an algorithmic-technique for solving problems recursively by trying to build a solution incrementally, one piece at a time, removing those solutions that fail to satisfy the constraints of the problem at any point of time (by time, here, is referred to the time elapsed till reaching any level of the search tree). Usually we can consider backtracking as DFS recursively traversal.
Backtracking template
1 2 3 4 5 6 7 8 9 10 11
funcbacktracking(...args) { if stop_condition { // Update the result set return } for i := range nodes_in_current_layer(...args) { // Down to next layer backtracking(...args, i + 1) // Go back to the upper layer } }
funccombine(n, k int) [][]int { result := [][]int{} path := []int{} var backtracking func(int, int, int) backtracking = func(n, k, index int) { iflen(path) == k { temp := make([]int, len(path)) copy(temp, path) result = append(result, temp) return } // For example, given n = 4, k = 3, if path is empty, n - (k - 0) + 1 = 2 means the last valid index can be 2 for i := index; i <= n - (k - len(path)) + 1; i++ { path = append(path, i) backtracking(n, k, i + 1) path = path[:len(path) - 1] } } backtracking(n, k, 1) return result }
Since we can convert a combination backtracking problem to a DFS traversal problem, if we don’t want to have the duplicated combination result item, it means we can’t pick duplicated nodes from the same layer of a tree. According to the backtracking template, in side of the backtracking for-loop we are handling the same layer logic (push/pop). At this point, if the given candidates is a sorted slice, we just need to compare if the previous element equals to the current element in the same layer.