2021-08-10:给定一个正数数组arr,返回arr的子集不能累加出的最小正数。1)正常怎么做? 2)如果arr中肯定有1这个值,怎么做?
福大大 答案2021-08-10:
先排序,然后扩充range范围。
1.b<=range+1,扩充到range+b。
2.b>range+1,直接返回range+1。
时间复杂度:排序的。
空间复杂度:排序的。
代码用golang编写。代码如下:
package main import ( "fmt" "math" "sort" ) func main() { arr := []int{1, 2, 5} if true { ret := unformedSum1(arr) fmt.Println(ret) } if true { ret := unformedSum2(arr) fmt.Println(ret) } if true { ret := unformedSum3(arr) fmt.Println(ret) } } func unformedSum1(arr []int) int { if len(arr) == 0 { return 1 } set := make(map[int]struct{}) process(arr, 0, 0, set) min := math.MaxInt64 for i := 0; i != len(arr); i++ { min = getMin(min, arr[i]) } for i := min + 1; i != math.MinInt64; i++ { if _, ok := set[i]; !ok { return i } } return 0 } func getMin(a int, b int) int { if a < b { return a } else { return b } } func process(arr []int, i int, sum int, set map[int]struct{}) { if i == len(arr) { set[sum] = struct{}{} return } process(arr, i+1, sum, set) process(arr, i+1, sum+arr[i], set) } func unformedSum2(arr []int) int { if len(arr) == 0 { return 1 } sum := 0 min := math.MaxInt64 for i := 0; i != len(arr); i++ { sum += arr[i] min = getMin(min, arr[i]) } // boolean[][] dp ... N := len(arr) dp := make([][]bool, N) for i := 0; i < N; i++ { dp[i] = make([]bool, sum+1) } for i := 0; i < N; i++ { // arr[0..i] 0 dp[i][0] = true } dp[0][arr[0]] = true for i := 1; i < N; i++ { for j := 1; j <= sum; j++ { if j-arr[i] >= 0 { dp[i][j] = dp[i-1][j] || (dp[i-1][j-arr[i]]) } else { dp[i][j] = dp[i-1][j] || (false) } } } for j := min; j <= sum; j++ { if !dp[N-1][j] { return j } } return sum + 1 } // 已知arr中肯定有1这个数 func unformedSum3(arr []int) int { if len(arr) == 0 { return 0 } sort.Slice(arr, func(i, j int) bool { return arr[i] < arr[j] // O (N * logN) }) range2 := 1 // arr[0] == 1 for i := 1; i != len(arr); i++ { if arr[i] > range2+1 { return range2 + 1 } else { range2 += arr[i] } } return range2 + 1 }
执行结果如下: