20230527给你一个只包含小写英
2023/11/30 来源:不详 浏览次数:次-05-27:给你一个只包含小写英文字母的字符串s。
每一次操作,你可以选择s中两个相邻的字符,并将它们交换。
请你返回将s变成回文串的最少操作次数。
注意,输入数据会确保s一定能变成一个回文串。
输入:s="letelt"。
输出:2。
答案-05-27:
大体过程如下:1.定义结构体IndexTree,其中包含一个整形切片tree和整型变量n,用于实现树状数组。
2.定义函数createIndexTree(sizeint)*IndexTree,用于创建一个大小为size的树状数组并初始化,返回该数组的指针。
.定义函数sum(it*IndexTree,iint)int,用于求以i为结尾的前缀和。
4.定义函数add(it*IndexTree,iint,vint),用于将第个位置上的值增加v。
5.定义函数merge(arr[]int,help[]int,lint,mint,rint)int,用于归并排序并统计逆序对数量。
6.定义函数number(arr[]int,help[]int,lint,rint)int,用于递归地求解整个序列中的逆序对数量。
7.定义函数minMovesToMakePalindrome(sstring)int,用于求解将字符串s变成回文串的最少操作次数。首先遍历字符串,将每个字符第一次出现的下标加入到对应字符的索引列表中。然后定义一个整形切片arr用于记录每个字符与其对称位置之间的距离,以及一个类型的变量it用于记录每个字符在左半部分的逆序对数量。遍历整个字符串,对于每个未处理的位置,找到它与其对称位置之间的距离,并计算出在左半部分有多少个字符与该字符构成了逆序对。最后调用number函数求解中的逆序对数量即可。
8.在main函数中定义字符串s="letelt",并调用minMovesToMakePalindrome函数输出结果。
时间复杂度为$O(n\logn)$,空间复杂度为$O(n)$。
其中,遍历整个字符串的时间复杂度为$O(n)$,建立字符索引列表的时间复杂度为$O(n)$,建立树状数组的时间复杂度为$O(n\logn)$,递归求解逆序对数量的时间复杂度为$O(n\logn)$,归并排序中合并两个有序子序列的时间复杂度为$O(n)$。
而空间复杂度中,建立字符索引列表占用的空间为$O(26n)$,建立树状数组占用的空间为$O(n\logn)$,递归求解逆序对数量时传递的辅助数组占用的空间为$O(n)$。
go语言完整代码如下:packagemainimport"fmt"funcmain(){s:="letelt"result:=minMovesToMakePalindrome(s)fmt.Println(result)}func(sstring)int{n:=len(s)indies:=make([][]int,26)fori:=0;i26;i++{indies[i]=[]int{}}fori:=0;in;i++{c:=int(s[i])-aindies[c]=append(indies[c],i+1)}arr:=make([]int,n+1)it:=newIndexTree(n)fori,l:=0,1;in;i,l=i+1,l+1{ifarr[l]==0{c:=int(s[i])-r:=indies[c][len(indies[c])-1]indies[c]=indies[c][:len(indies[c])-1]ifl==r{arr[l]=(1+n)/2it.add(l,-1)}else{kth:=it.sum(l)arr[l]=ktharr[r]=n-kth+1it.add(r,-1)}}}returnnumber(arr,make([]int,n+1),1,n)}typeindexTreestruct{tree[]intnint}funcnewIndexTree(sizeint)*indexTree{tree:=make([]int,size+1)ans:=indexTree{tree:tree,n:size}fori:=1;i=size;i++{ans.add(i,1)}returnans}func(it*indexTree)sum(iint)int{ans:=0fori0{ans+=it.tree[i]i-=i-i}returnans}func(it*indexTree)add(iint,vint){forilen(it.tree){it.tree[i]+=vi+=i-i}}funcnumber(arr[]int,help[]int,lint,rint)int{ifl=r{return0}mid:=l+((r-l)1)returnnumber(arr,help,l,mid)+number(arr,help,mid+1,r)+merge(arr,help,l,mid,r)}funcmerge(arr[]int,help[]int,lint,mint,rint)int{i:=rp1:=mp2:=rans:=0forp1=lp2m{ifarr[p1]arr[p2]{ans+=p2-mhelp[i]=arr[p1]i--p1--}else{help[i]=arr[p2]i--p2--}}forp1=l{help[i]=arr[p1]i--p1--}forp2m{help[i]=arr[p2]i--p2--}fori:=l;i=r;i++{arr[i]=help[i]}returnans}
在这里插入图片描述
rust语言完整代码如下:fnmain(){lets=String::from("letelt");letresult=min_moves_to_make_palindrome(s);println!("{}",result);}fnmin_moves_to_make_palindrome(s:String)-i2{letn=s.len();letmutindies:VecVeci2=vec![vec![];26];for(i,c)ins.chars().enumerate(){letindex=(casu8-ba)asusize;indies[index].push((i+1)asi2);}letmutarr:Veci2=vec![0;nasusize+1];letmutit=IndexTree::new(nasi2);letmuti=0;letmutl=1;whilein{ifarr[lasusize]==0{letc_index=(s.chars().nth(iasusize).unwrap()asu8-ba)asusize;leta=indies[c_index].len()-1;letr=indies[c_index][a];indies[c_index].remove(a);ifl==r{arr[lasusize]=(1+nasi2)/2;it.add(l,-1);}else{letkth=it.sum(l);arr[lasusize]=kth;arr[rasusize]=nasi2-kth+1;it.add(r,-1);}}i+=1;l+=1;}number(mutarr,mutvec![0;nasusize+1],1,nasi2)}structIndexTree{tree:Veci2,n:i2,}implIndexTree{fnnew(size:i2)-Self{lettree=vec![0;sizeasusize+1];letmutans=Self{tree,n:size};foriin1..=size{ans.add(i,1);}returnans;}fnsum(self,muti:i2)-i2{letmutans=0;whilei0{ans+=self.tree[iasusize];i-=i-i;}ans}fnadd(mutself,muti:i2,v:i2){whileiself.tree.len()asi2{self.tree[iasusize]+=v;i+=i-i;}}}fnnumber(arr:mutVeci2,help:mutVeci2,l:i2,r:i2)-i2{ifl=r{return0;}letmid=l+((r-l)1);returnnumber(arr,help,l,mid)+number(arr,help,mid+1,r)+merge(arr,help,l,mid,r);}fnmerge(arr:mutVeci2,help:mutVeci2,l:i2,m:i2,r:i2)-i2{letmuti=r;letmutp1=m;letmutp2=r;letmutans=0;whilep1=lp2m{ans+=ifarr[p1asusize]arr[p2asusize]{p2-m}else{0};ifarr[p1asusize]arr[p2asusize]{help[iasusize]=arr[p1asusize];p1-=1;}else{help[iasusize]=arr[p2asusize];p2-=1;};i-=1;}whilep1=l{help[iasusize]=arr[p1asusize];i-=1;p1-=1;}whilep2m{help[iasusize]=arr[p2asusize];i-=1;p2-=1;}foriinl..=r{arr[iasusize]=help[iasusize];}ans}
在这里插入图片描述
在这里插入图片描述