给定一个字符串str,由小写英文字母的,任务是计算除去以得到通过以下操作空字符串中的字符的索引(基于1索引)的总和:
- 删除字符串最小的字母。
- 对于多次出现的最小字母,请删除出现在最小索引处的那个字母。
- 删除每个字符,其右边所有字符的索引都会减少1。
例子:
Input: str = “aba”
Output: 4
Explanation:“aba” -> “ba”, Sum = 1
“ba” -> “b”, Sum = 1 + 2 = 3
“b” -> “”, Sum = 3 + 1 = 4
Input: str = “geeksforgeeks”
Output: 41
天真的方法:
请按照以下步骤解决问题:
- 查找具有最小索引的最小字符。
- 从字符串删除该字符,然后将所有字符向右移一个索引。
- 重复上述步骤,直到字符串为空。
时间复杂度: O(N ^ 2)
辅助空间: O(N)
高效的方法:可以使用分段树和散列来优化上述方法。请按照以下步骤解决问题:
- 可以观察到,仅删除字符右侧的索引会受到影响,也就是说,它们需要移动一个位置。
- 将字符的索引存储在HashMap中
- 处理HashMap中的字符。
- 使用段树,找到留在字符当前索引中的元素数量,这些元素已从字符串删除。
- 提取已删除字符的索引,并在段树中的[0,已提取元素的索引]范围内进行搜索,并找到段树中存在范围内的索引计数。
- 添加已提取元素的索引–计算答案,然后将当前已删除元素的索引插入到细分树中。
- 重复上述步骤,直到字符串为空。
下面是上述方法的实现:
C++
// C++ Program to implement
// the above approach
#include
using namespace std;
// Function to add index of the deleted character
void add_seg(int seg[], int start, int end, int current,
int index)
{
// If index is beyond the range
if (index > end or index < start)
return;
// Insert the index of the deleted
// characeter
if (start == end) {
seg[current] = 1;
return;
}
int mid = (start + end) / 2;
// Search over the subtrees to find the
// desired index
add_seg(seg, start, mid, 2 * current + 1, index);
add_seg(seg, mid + 1, end, 2 * current + 2, index);
seg[current]
= seg[2 * current + 1] + seg[2 * current + 2];
}
// Function to return count of deleted indices
// which are to the left of the current index
int deleted(int seg[], int l, int r, int start, int end,
int current)
{
if (end < l or start > r)
return 0;
if (start >= l and end <= r)
return seg[current];
int mid = (start + end) / 2;
return deleted(seg, l, r, start, mid, 2 * current + 1)
+ deleted(seg, l, r, mid + 1, end,
2 * current + 2);
}
// Function to generate the
// sum of indices
void sumOfIndices(string s)
{
int N = s.size();
int x = int(ceil(log2(N)));
int seg_size = 2 * (int)pow(2, x) - 1;
int segment[seg_size] = { 0 };
int count = 0;
// Stores the original index of the
// characters in sorted order of key
map > fre;
for (int i = 0; i < N; i++) {
fre[s[i]].push(i);
}
// Traverse the map
while (fre.empty() == false) {
// Extract smallest index
// of smallest characetr
auto it = fre.begin();
// Delete the character from the map
// if it has no remaining occurrence
if (it->second.empty() == true)
fre.erase(it->first);
else {
// Stores the original index
int original_index
= it->second.front();
// Count of elements removed to
// the left of current character
int curr_index
= deleted(segment, 0, original_index - 1,
0, N - 1, 0);
// Current index of the current character
int new_index
= original_index - curr_index;
// For 1-based indexing
count += new_index + 1;
// Insert the deleted index
// in the segment tree
add_seg(segment, 0, N - 1,
0, original_index);
it->second.pop();
}
}
// Final answer
cout << count << endl;
}
// Driver Code
int main()
{
string s = "geeksforgeeks";
sumOfIndices(s);
}
Java
// Java program to implement
// the above approach
import java.io.*;
import java.lang.*;
import java.util.*;
class GFG{
// Function to add index of the deleted character
static void add_seg(int seg[], int start, int end,
int current, int index)
{
// If index is beyond the range
if (index > end || index < start)
return;
// Insert the index of the deleted
// characeter
if (start == end)
{
seg[current] = 1;
return;
}
int mid = (start + end) / 2;
// Search over the subtrees to find the
// desired index
add_seg(seg, start, mid, 2 * current + 1, index);
add_seg(seg, mid + 1, end, 2 * current + 2, index);
seg[current] = seg[2 * current + 1] +
seg[2 * current + 2];
}
// Function to return count of deleted indices
// which are to the left of the current index
static int deleted(int seg[], int l, int r, int start,
int end, int current)
{
if (end < l || start > r)
return 0;
if (start >= l && end <= r)
return seg[current];
int mid = (start + end) / 2;
return deleted(seg, l, r, start, mid,
2 * current + 1) +
deleted(seg, l, r, mid + 1, end,
2 * current + 2);
}
// Function to generate the
// sum of indices
static void sumOfIndices(String s)
{
int N = s.length();
int x = (int)(Math.ceil(Math.log(N) / Math.log(2)));
int seg_size = 2 * (int)Math.pow(2, x) - 1;
int segment[] = new int[seg_size];
int count = 0;
// Stores the original index of the
// characters in sorted order of key
TreeMap> fre = new TreeMap<>();
for(int i = 0; i < N; i++)
{
int key = (int)(s.charAt(i));
ArrayDeque que = fre.getOrDefault(
key, new ArrayDeque<>());
que.addLast(i);
fre.put(key, que);
}
// Traverse the map
while (!fre.isEmpty())
{
// Extract smallest index
// of smallest characetr
int it = fre.firstKey();
// Delete the character from the map
// if it has no remaining occurrence
if (fre.get(it).size() == 0)
fre.remove(it);
else
{
ArrayDeque que = fre.get(it);
// Stores the original index
int original_index = que.getFirst();
// System.out.println(original_index);
// Count of elements removed to
// the left of current character
int curr_index = deleted(segment, 0,
original_index - 1,
0, N - 1, 0);
// Current index of the current character
int new_index = original_index - curr_index;
// For 1-based indexing
count += new_index + 1;
// Insert the deleted index
// in the segment tree
add_seg(segment, 0, N - 1, 0,
original_index);
que.removeFirst();
fre.put(it, que);
}
}
// Final answer
System.out.println(count);
}
// Driver Code
public static void main(String[] args)
{
String s = "geeksforgeeks";
sumOfIndices(s);
}
}
// This code is contributed by Kingash
输出:
41
时间复杂度: O(N log N)
辅助空间: O(N)