Standard Priority Queue VI

For this problem you use a priority queue to keep track of the indexes to remove later on. Also, the size of the priority queue matters here, need to be minimum otherwise it runs into memory limit exceeded. Keep in mind that the string concatenation also leads to TLE, so need to use a StringBuilder and only convert to string at the return step. Code is down below, cheers, ACC.

Lexicographically Minimum String After Removing Stars - LeetCode

3170. Lexicographically Minimum String After Removing Stars
Medium

You are given a string s. It may contain any number of '*' characters. Your task is to remove all '*' characters.

While there is a '*', do the following operation:

  • Delete the leftmost '*' and the smallest non-'*' character to its left. If there are several smallest characters, you can delete any of them.

Return the lexicographically smallest resulting string after removing all '*' characters.

 

Example 1:

Input: s = "aaba*"

Output: "aab"

Explanation:

We should delete one of the 'a' characters with '*'. If we choose s[3]s becomes the lexicographically smallest.

Example 2:

Input: s = "abc"

Output: "abc"

Explanation:

There is no '*' in the string.

 

Constraints:

  • 1 <= s.length <= 105
  • s consists only of lowercase English letters and '*'.
  • The input is generated such that it is possible to delete all '*' characters.

public class Solution {
    public string ClearStars(string s)
    {
        PriorityQueue pQueue = new PriorityQueue(true, 100000 + 7);
        Hashtable skipChars = new Hashtable();
        for (int i = 0; i < s.Length; i++)
        {
            if (s[i] != '*')
                pQueue.Enqueue(i, (int)s[i] * (100000 + 7) + s.Length - i);
            else
            {
                if (pQueue.Count > 0)
                {
                    double priority = 0;
                    int index = (int)pQueue.Dequeue(out priority);
                    if (!skipChars.ContainsKey(index)) skipChars.Add(index, true);
                }
                skipChars.Add(i, true);
            }
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < s.Length; i++)
            if (!skipChars.ContainsKey(i)) sb.Append(s[i]);

        return sb.ToString();
    }
    
    public class PriorityQueue
{
    public struct HeapEntry
    {
        private object item;
        private double priority;
        public HeapEntry(object item, double priority)
        {
            this.item = item;
            this.priority = priority;
        }
        public object Item
        {
            get
            {
                return item;
            }
        }
        public double Priority
        {
            get
            {
                return priority;
            }
        }
    }

    private bool ascend;
    private int count;
    private int capacity;
    private HeapEntry[] heap;

    public int Count
    {
        get
        {
            return this.count;
        }
    }

    public PriorityQueue(bool ascend, int cap = -1)
    {
        capacity = 10000000;
        if (cap > 0) capacity = cap;
        heap = new HeapEntry[capacity];
        this.ascend = ascend;
    }

    public object Dequeue(out double priority)
    {
        priority = heap[0].Priority;
        object result = heap[0].Item;
        count--;
        trickleDown(0, heap[count]);
        return result;
    }
    public object Peak(out double priority)
    {
        priority = heap[0].Priority;
        object result = heap[0].Item;
        return result;
    }

    public object Peak(/*out double priority*/)
    {
        //priority = heap[0].Priority;
        object result = heap[0].Item;
        return result;
    }

    public void Enqueue(object item, double priority)
    {
        count++;
        bubbleUp(count - 1, new HeapEntry(item, priority));
    }

    private void bubbleUp(int index, HeapEntry he)
    {
        int parent = (index - 1) / 2;
        // note: (index > 0) means there is a parent
        if (this.ascend)
        {
            while ((index > 0) && (heap[parent].Priority > he.Priority))
            {
                heap[index] = heap[parent];
                index = parent;
                parent = (index - 1) / 2;
            }
            heap[index] = he;
        }
        else
        {
            while ((index > 0) && (heap[parent].Priority < he.Priority))
            {
                heap[index] = heap[parent];
                index = parent;
                parent = (index - 1) / 2;
            }
            heap[index] = he;
        }
    }

    private void trickleDown(int index, HeapEntry he)
    {
        int child = (index * 2) + 1;
        while (child < count)
        {
            if (this.ascend)
            {
                if (((child + 1) < count) &&
                    (heap[child].Priority > heap[child + 1].Priority))
                {
                    child++;
                }
            }
            else
            {
                if (((child + 1) < count) &&
                    (heap[child].Priority < heap[child + 1].Priority))
                {
                    child++;
                }
            }
            heap[index] = heap[child];
            index = child;
            child = (index * 2) + 1;
        }
        bubbleUp(index, he);
    }
}

}

Comments

Popular posts from this blog

Golang vs. C#: performance characteristics (simple case study)

ProjectEuler Problem 719 (some hints, but no spoilers)

Changing the root of a binary tree