📌  相关文章
📜  根据给定条件删除的字符索引总和以获得空字符串

📅  最后修改于: 2021-05-17 22:22:43             🧑  作者: Mango

给定一个字符串str,由小写英文字母的,任务是计算除去以得到通过以下操作空字符串中的字符的索引(基于1索引)的总和:

  • 删除字符串最小的字母。
  • 对于多次出现的最小字母,请删除出现在最小索引处的那个字母。
  • 删除每个字符,其右边所有字符的索引都会减少1。

例子:

天真的方法:
请按照以下步骤解决问题:

  • 查找具有最小索引的最小字符。
  • 从字符串删除该字符,并将所有字符向右移一个索引。
  • 重复上述步骤,直到字符串为空。

时间复杂度: 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)