

2023-05-27:给你一个只包含小写英文字母的字符串 s 。 每一次 操作 ,你可以选择 s...
source link: https://www.cnblogs.com/moonfdd/p/17437351.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

2023-05-27:给你一个只包含小写英文字母的字符串 s 。
每一次 操作 ,你可以选择 s 中两个 相邻 的字符,并将它们交换。
请你返回将 s 变成回文串的 最少操作次数 。
注意 ,输入数据会确保 s 一定能变成一个回文串。
输入:s = "letelt"。
输出:2。
答案2023-05-27:
大体过程如下:
1.定义结构体 IndexTree
,其中包含一个整型切片 tree
和整型变量 n
,用于实现树状数组。
2.定义函数 createIndexTree(size int) *IndexTree
,用于创建一个大小为 size
的树状数组并初始化,返回该数组的指针。
3.定义函数 sum(it *IndexTree, i int) int
,用于求以 i
为结尾的前缀和。
4.定义函数 add(it *IndexTree, i int, v int)
,用于将第 i
个位置上的值增加 v
。
5.定义函数 merge(arr []int, help []int, l int, m int, r int) int
,用于归并排序并统计逆序对数量。
6.定义函数 number(arr []int, help []int, l int, r int) int
,用于递归地求解整个序列中的逆序对数量。
7.定义函数 minMovesToMakePalindrome(s string) int
,用于求解将字符串 s
变成回文串的最少操作次数。首先遍历字符串,将每个字符第一次出现的下标加入到对应字符的索引列表中。然后定义一个整型切片 arr
用于记录每个字符与其对称位置之间的距离,以及一个 IndexTree
类型的变量 it
用于记录每个字符在左半部分的逆序对数量。遍历整个字符串,对于每个未处理的位置,找到它与其对称位置之间的距离,并计算出在左半部分有多少个字符与该字符构成了逆序对。最后调用 number
函数求解 arr
中的逆序对数量即可。
8.在 main
函数中定义字符串 s = "letelt"
,并调用 minMovesToMakePalindrome
函数输出结果。
时间复杂度为 $O(n\log n)$,空间复杂度为 $O(n)$。
其中,遍历整个字符串的时间复杂度为 $O(n)$,建立字符索引列表的时间复杂度为 $O(n)$,建立树状数组的时间复杂度为 $O(n\log n)$,递归求解逆序对数量的时间复杂度为 $O(n\log n)$,归并排序中合并两个有序子序列的时间复杂度为 $O(n)$。
而空间复杂度中,建立字符索引列表占用的空间为 $O(26n)$,建立树状数组占用的空间为 $O(n\log n)$,递归求解逆序对数量时传递的辅助数组占用的空间为 $O(n)$。
go语言完整代码如下:
package main
import "fmt"
func main() {
s := "letelt"
result := minMovesToMakePalindrome(s)
fmt.Println(result)
}
func minMovesToMakePalindrome(s string) int {
n := len(s)
indies := make([][]int, 26)
for i := 0; i < 26; i++ {
indies[i] = []int{}
}
for i := 0; i < n; i++ {
c := int(s[i]) - 'a'
indies[c] = append(indies[c], i+1)
}
arr := make([]int, n+1)
it := newIndexTree(n)
for i, l := 0, 1; i < n; i, l = i+1, l+1 {
if arr[l] == 0 {
c := int(s[i]) - 'a'
r := indies[c][len(indies[c])-1]
indies[c] = indies[c][:len(indies[c])-1]
if l == r {
arr[l] = (1 + n) / 2
it.add(l, -1)
} else {
kth := it.sum(l)
arr[l] = kth
arr[r] = n - kth + 1
it.add(r, -1)
}
}
}
return number(arr, make([]int, n+1), 1, n)
}
type indexTree struct {
tree []int
n int
}
func newIndexTree(size int) *indexTree {
tree := make([]int, size+1)
ans := &indexTree{tree: tree, n: size}
for i := 1; i <= size; i++ {
ans.add(i, 1)
}
return ans
}
func (it *indexTree) sum(i int) int {
ans := 0
for i > 0 {
ans += it.tree[i]
i -= i & -i
}
return ans
}
func (it *indexTree) add(i int, v int) {
for i < len(it.tree) {
it.tree[i] += v
i += i & -i
}
}
func number(arr []int, help []int, l int, r int) int {
if l >= r {
return 0
}
mid := l + ((r - l) >> 1)
return number(arr, help, l, mid) + number(arr, help, mid+1, r) + merge(arr, help, l, mid, r)
}
func merge(arr []int, help []int, l int, m int, r int) int {
i := r
p1 := m
p2 := r
ans := 0
for p1 >= l && p2 > m {
if arr[p1] > arr[p2] {
ans += p2 - m
help[i] = arr[p1]
i--
p1--
} else {
help[i] = arr[p2]
i--
p2--
}
}
for p1 >= l {
help[i] = arr[p1]
i--
p1--
}
for p2 > m {
help[i] = arr[p2]
i--
p2--
}
for i := l; i <= r; i++ {
arr[i] = help[i]
}
return ans
}
rust语言完整代码如下:
fn main() {
let s = String::from("letelt");
let result = min_moves_to_make_palindrome(s);
println!("{}", result);
}
fn min_moves_to_make_palindrome(s: String) -> i32 {
let n = s.len();
let mut indies: Vec<Vec<i32>> = vec![vec![]; 26];
for (i, c) in s.chars().enumerate() {
let index = (c as u8 - b'a') as usize;
indies[index].push((i + 1) as i32);
}
let mut arr: Vec<i32> = vec![0; n as usize + 1];
let mut it = IndexTree::new(n as i32);
let mut i = 0;
let mut l = 1;
while i < n {
if arr[l as usize] == 0 {
let c_index = (s.chars().nth(i as usize).unwrap() as u8 - b'a') as usize;
let a = indies[c_index].len() - 1;
let r = indies[c_index][a];
indies[c_index].remove(a);
if l == r {
arr[l as usize] = (1 + n as i32) / 2;
it.add(l, -1);
} else {
let kth = it.sum(l);
arr[l as usize] = kth;
arr[r as usize] = n as i32 - kth + 1;
it.add(r, -1);
}
}
i += 1;
l += 1;
}
number(&mut arr, &mut vec![0; n as usize + 1], 1, n as i32)
}
struct IndexTree {
tree: Vec<i32>,
n: i32,
}
impl IndexTree {
fn new(size: i32) -> Self {
let tree = vec![0; size as usize + 1];
let mut ans = Self { tree, n: size };
for i in 1..=size {
ans.add(i, 1);
}
return ans;
}
fn sum(&self, mut i: i32) -> i32 {
let mut ans = 0;
while i > 0 {
ans += self.tree[i as usize];
i -= i & -i;
}
ans
}
fn add(&mut self, mut i: i32, v: i32) {
while i < self.tree.len() as i32 {
self.tree[i as usize] += v;
i += i & -i;
}
}
}
fn number(arr: &mut Vec<i32>, help: &mut Vec<i32>, l: i32, r: i32) -> i32 {
if l >= r {
return 0;
}
let mid = l + ((r - l) >> 1);
return number(arr, help, l, mid) + number(arr, help, mid + 1, r) + merge(arr, help, l, mid, r);
}
fn merge(arr: &mut Vec<i32>, help: &mut Vec<i32>, l: i32, m: i32, r: i32) -> i32 {
let mut i = r;
let mut p1 = m;
let mut p2 = r;
let mut ans = 0;
while p1 >= l && p2 > m {
ans += if arr[p1 as usize] > arr[p2 as usize] {
p2 - m
} else {
0
};
if arr[p1 as usize] > arr[p2 as usize] {
help[i as usize] = arr[p1 as usize];
p1 -= 1;
} else {
help[i as usize] = arr[p2 as usize];
p2 -= 1;
};
i -= 1;
}
while p1 >= l {
help[i as usize] = arr[p1 as usize];
i -= 1;
p1 -= 1;
}
while p2 > m {
help[i as usize] = arr[p2 as usize];
i -= 1;
p2 -= 1;
}
for i in l..=r {
arr[i as usize] = help[i as usize];
}
ans
}
c++完整代码如下:
#include <iostream>
#include <vector>
using namespace std;
struct IndexTree {
vector<int> tree;
int n;
IndexTree(int size) {
tree.resize(size + 1);
n = size;
for (int i = 1; i <= n; i++) {
add(i, 1);
}
}
int sum(int i) {
int ans = 0;
while (i > 0) {
ans += tree[i];
i -= i & -i;
}
return ans;
}
void add(int i, int v) {
while (i < tree.size()) {
tree[i] += v;
i += i & -i;
}
}
};
int merge(vector<int>& arr, vector<int>& help, int l, int m, int r);
int number(vector<int>& arr, vector<int>& help, int l, int r) {
if (l >= r) {
return 0;
}
int mid = l + ((r - l) >> 1);
return number(arr, help, l, mid) + number(arr, help, mid + 1, r) + merge(arr, help, l, mid, r);
}
int merge(vector<int>& arr, vector<int>& help, int l, int m, int r) {
int i = r;
int p1 = m;
int p2 = r;
int ans = 0;
while (p1 >= l && p2 > m) {
if (arr[p1] > arr[p2]) {
ans += p2 - m;
help[i--] = arr[p1--];
}
else {
help[i--] = arr[p2--];
}
}
while (p1 >= l) {
help[i--] = arr[p1--];
}
while (p2 > m) {
help[i--] = arr[p2--];
}
for (i = l; i <= r; i++) {
arr[i] = help[i];
}
return ans;
}
int minMovesToMakePalindrome(char* s) {
int n = strlen(s);
vector<vector<int>> indies(26, vector<int>());
for (int i = 0, j = 1; i < n; i++, j++) {
int c = s[i] - 'a';
indies[c].push_back(j);
}
vector<int> arr(n + 1, 0);
IndexTree it(n);
for (int i = 0, l = 1; i < n; i++, l++) {
if (arr[l] == 0) {
int c = s[i] - 'a';
int r = indies[c].back();
indies[c].pop_back();
if (l == r) {
arr[l] = (1 + n) / 2;
it.add(l, -1);
}
else {
int kth = it.sum(l);
arr[l] = kth;
arr[r] = n - kth + 1;
it.add(r, -1);
}
}
}
vector<int> help(n + 1, 0);
int ans = number(arr, help, 1, n);
return ans;
}
int main() {
char s[] = "letelt";
int result = minMovesToMakePalindrome(s);
cout << result << endl;
return 0;
}
Recommend
-
109
技术成就梦想51CTO-中国领先的IT技术网站 您浏览的内容找不到或已被删除
-
6
A股企业代码前的英文字母都是什么含义? 1998年4月22日,沪深交易所宣布,将对财务状况或其它状况出现异常的上市公司股票交易进行特别处理(Specialtreatment),并在简称前冠以“ST”,因此这类股票称为ST股。
-
28
分享三个纯CSS实现26个英文字母的案例 这篇文章发布于 2019年01月11日,星期五,11:30,归类于 CSS相关。 阅读 17822 次, 今日 5 次...
-
10
你该好好学习 2021-10-23 11:49 采纳率: 50% 浏览 172 存储过程,计算一个字符...
-
5
Java--字符串使用StringTokenizer来分割字符,由小写转大写,由大写转小写 精选 原创 小小迷糊...
-
7
HBUACM1-3 英文字母 发表于 2023-01-07| 更新于...
-
6
会动的26个英文字母设计, 每个字母动画都很好玩 2月 1, 2023 发表于: 网页设计 &...
-
25
记一次接口调用字段映射失败问题排查 在写接口的时候遇到一个很神奇的问题,编写一个post接口,在使用包装类接收body的时候发现有个字段映射不上。代码如下 @RestController public class TestCont...
-
4
【笨問題】無法輸入英文小寫字母 2013-07-06 10:55 AM 10
-
7
寻找一款念英文字母能识别为单词,并翻译为中文的 APP 或小程序 V2EX › 问与...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK