2024-12-23:找出分数最低的排列。用go语言,给定一个数组 nums,它包含从 0 到 n-1 的一个排列。
我们定义一个排列 perm 的分数为:
score(perm) = |perm[0] - nums[perm[1]]| + |perm[1] - nums[perm[2]]| + ... + |perm[n - 1] - nums[perm[0]]|
任务是找出一个排列 perm,使得其分数最低。
如果有多个排列的分数相同,则需要返回字典序最小的那个排列。
2 <= n == nums.length <= 14。
nums 是 [0, 1, 2, ..., n - 1] 的一个排列。
输入:nums = [1,0,2]。
输出:[0,1,2]。
字典序最小且分数最低的排列是 [0,1,2]。这个排列的分数是 |0 - 0| + |1 - 2| + |2 - 1| = 2 。
答案2024-12-23:
chatgpt[1]
题目来自leetcode3149。
1.计算分数的过程是根据给定的 perm 排列计算|perm[0] - nums[perm[1]]| + |perm[1] - nums[perm[2]]| + ... + |perm[n - 1] - nums[perm[0]|,即每个 perm[i] 与对应 nums[perm[i]] 之间的绝对差的和。
2.使用动态规划来解决这个问题,首先初始化一个数组 f,并使用一个数组 g 来记录每一步得到的结果对应的下一步的选择。
3.从后往前遍历,更新分数,然后回溯找出结果。
总的时间复杂度:
总的额外空间复杂度:
package main
import(
"fmt"
"math/bits"
"math"
)
func findPermutation(a []int)[]int{
n :=len(a)
u :=1<<n -1
f :=make([][]int,1<<n)
g :=make([][]int,1<<n)
for i :=range f {
f[i]=make([]int, n)
for j :=range f[i]{
f[i][j]= math.MaxInt
}
g[i]=make([]int, n)
}
for j :=range f[u]{
f[u][j]= abs(j - a[0])
g[u][j]=-1
}
for s := u -2; s >0; s -=2{// 注意偶数不含 0,是无效状态
for _s :=uint(s); _s >0; _s &= _s -1{
j := bits.TrailingZeros(_s)
for cus, lb := u^s,0; cus >0; cus ^= lb {
lb = cus &-cus
k := bits.TrailingZeros(uint(lb))
v := f[s|lb][k]+ abs(j-a[k])
if v < f[s][j]{
f[s][j]= v
g[s][j]= k
}
}
}
}
ans :=make([]int,0, n)
for s, j :=0,0; j >=0;{
ans =append(ans, j)
s |=1<< j
j = g[s][j]
}
return ans
}
func abs(x int)int{if x <0{return-x };return x }
func main(){
a :=[]int{1,0,2}
fmt.Println(findPermutation(a))
}
[1]
chatgpt: https://chatbotsplace.com/?rc=nnNWSCJ7EP