funcspecialPerm(nums []int)int { n := len(nums) memo := make([][]int, 1<<n-1) for i := range memo { memo[i] = make([]int, n) for j := range memo[i] { memo[i][j] = -1// -1 表示没有计算过 } } var dfs func(int, int)int dfs = func(s int, i int)int { if s == 1<<n { return1// 找到一个特别排列 } if memo[s][i] != -1 { return memo[s][i] } res := 0 for j, x := range nums { if s>>j&1 == 0 && (nums[i]%x == 0 || x%nums[i] == 0) { res += dfs(s|1<<j, j) } } memo[s][i] = res return res } ans := 0 for i := range nums { ans += dfs(1<<i, i) } return ans % 1e9 }
找到第一个大于 a 的字符,继续向右遍历,直到字符串末尾或者遇到了 a,这个区间内的所有字符减一就找到了答案。因为字符 a 减一会变成 z,这样就不是减小而是增大。
特殊的,如果字符串全是 a,题目要求必须操作一次,把最后一个 a 变成 z 即可。
1 2 3 4 5 6 7 8 9 10 11 12 13
funcsmallestString(s string)string { b := []byte(s) for i, c := range s { if c != 'a' { for ; i < len(b) && b[i] != 'a'; i++ { b[i]-- } returnstring(b) } } b[len(b)-1] = 'z' returnstring(b) }
funcremoveTrailingZeros(num string)string { b := []byte(num) for i := len(b) - 1; i >= 0; i-- { if b[i] != '0' { returnstring(b[:i+1]) } } return num }
funcfindTargetSumWays(nums []int, target int)int { sum := 0 for _, num := range nums { sum += num } sum -= abs(0, target) // p−q=target p+q=s, 2q=s-target if sum < 0 || sum%2 == 1 { return0 } m := sum / 2// 背包数量 n := len(nums) memo := make([][]int, n) for i := range memo { memo[i] = make([]int, m+1) for j := range memo[i] { memo[i][j] = -1 } } var dfs func(int, int)int dfs = func(i int, c int)int { if i < 0 { if c == 0 { return1 } return0 } if memo[i][c] == -1 { if c < nums[i] { memo[i][c] = dfs(i-1, c) } else { memo[i][c] = dfs(i-1, c) + dfs(i-1, c-nums[i]) } } return memo[i][c] } return dfs(n-1, m) }
funcfindTargetSumWays2(nums []int, target int)int { sum := 0 for _, num := range nums { sum += num } sum -= abs(0, target) // p−q=target p+q=s, 2q=s-target if sum < 0 || sum%2 == 1 { return0 } m := sum / 2// 背包数量 n := len(nums) dp := make([][]int, n+1) for i := range dp { dp[i] = make([]int, m+1) } dp[0][0] = 1 for i, num := range nums { for c := 0; c <= m; c++ { if c < num { dp[i+1][c] = dp[i][c] } else { dp[i+1][c] = dp[i][c] + dp[i][c-num] } } } return dp[n][m] }
funcfindTargetSumWays(nums []int, target int)int { sum := 0 for _, num := range nums { sum += num } sum -= abs(0, target) // p−q=target p+q=s, 2q=s-target if sum < 0 || sum%2 == 1 { return0 } m := sum / 2// 背包数量 n := len(nums) dp := make([][]int, 2) for i := range dp { dp[i] = make([]int, m+1) } dp[0][0] = 1 for i, num := range nums { for c := 0; c <= m; c++ { if c < num { dp[(i+1)%2][c] = dp[i%2][c] } else { dp[(i+1)%2][c] = dp[i%2][c] + dp[i%2][c-num] } } } return dp[n%2][m] }
funcfindTargetSumWays(nums []int, target int)int { sum := 0 for _, num := range nums { sum += num } sum -= abs(0, target) if sum < 0 || sum%2 == 1 { return0 } m := sum / 2// 背包数量 dp := make([]int, m+1) dp[0] = 1 for _, num := range nums { for c := m; c >= num; c-- { dp[c] += dp[c-num] } } return dp[m] }