ASCII Range Sum

Last Updated : 28 Jul, 2025

Given a string s consisting of lowercase English letters, identify all characters whose first and last occurrences are at different positions.
For each such character, compute the sum of ASCII values of all characters that lie strictly between its first and last occurrence.
Return a list of all non-zero sums. The order of sums does not matter.

Examples:

Input: s = "abacab"
Output: [293, 294]
Explanation: characters 'a' and 'b' appear more than one:
'a' : between positions 1 and 5 → characters are b, a, c and ascii sum is 98 + 97 + 99 = 294.
'b' : between positions 2 and 6 → characters are a, c, a and ascii sum is 97 + 99 + 97 = 293.

Input: s = "acdac"
Output: [197, 199]
Explanation: characters 'a' and 'c' appear more than one:
'a'  :  between positions 1 and 4 → characters are c, d and ascii sum is  99 + 100 = 199.
'c'  :  between positions 2 and 5 → characters are d, a and ascii sum is  100 + 97  = 197.

Try It Yourself
redirect icon

[Approach 1] - First-Last Index Brute Sum

In this approach, we first record the indices of all occurrences for each character in the string. For every character that appears more than once, we identify its first and last occurrence. Then, we traverse the substring strictly between these two positions and compute the sum of ASCII values of all characters in that range. Finally, we collect all such non-zero sums and return them. This method is simple but inefficient, as it may repeatedly scan large parts of the string for multiple characters.

C++
#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;

vector<int> asciirange(string &s) {
    
    // Store positions of each character
    unordered_map<char, vector<int>> pos;
    vector<int> result;

    // Track all occurrences of each character
    for (int i = 0; i < s.size(); i++) {
        pos[s[i]].push_back(i);
    }

    for (auto it : pos) {
        vector<int> idx = it.second;

        // Proceed only if the character 
        // appears more than once
        if (idx.size() >= 2) {
            int first = idx[0];
            int last = idx[idx.size() - 1];
            int sum = 0;

            // Compute ASCII sum of characters strictly 
            // between first and last occurrence
            for (int i = first + 1; i < last; i++) {
                sum += (int)s[i];
            }
            if(sum != 0){
                result.push_back(sum);
            }
        }
    }
    
    return result;
}

int main() {
    string s = "abacab";
    
    vector<int> result = asciirange(s);
    sort(result.begin(), result.end());
    
    for (int i = 0; i < result.size(); i++) {
        if (result[i] != 0)
            cout << result[i] << " ";
    }

    return 0;
}
Java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Collections;

class GfG {

    public static ArrayList<Integer> asciirange(String s) {
        
        // Store positions of each character
        HashMap<Character, ArrayList<Integer>> pos = new HashMap<>();
        ArrayList<Integer> result = new ArrayList<>();

        // Track all occurrences of each character
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            pos.putIfAbsent(ch, new ArrayList<>());
            pos.get(ch).add(i);
        }

        for (Map.Entry<Character, ArrayList<Integer>> it : pos.entrySet()) {
            ArrayList<Integer> idx = it.getValue();

            // Proceed only if the character 
            // appears more than once
            if (idx.size() >= 2) {
                int first = idx.get(0);
                int last = idx.get(idx.size() - 1);
                int sum = 0;

                // Compute ASCII sum of characters strictly 
                // between first and last occurrence
                for (int i = first + 1; i < last; i++) {
                    sum += (int) s.charAt(i);
                }
                
                if(sum != 0){
                    result.add(sum);
                }
            }
        }

        return result;
    }

    public static void main(String[] args) {
        String s = "abacab";
        
        ArrayList<Integer> result = asciirange(s);
        Collections.sort(result);
        
        for (int val : result) {
            if (val != 0) {
                System.out.print(val + " ");
            }
        }
    }
}
Python
def asciirange(s):
    # Store positions of each character
    pos = {}
    result = []

    # Track all occurrences of each character
    for i in range(len(s)):
        if s[i] not in pos:
            pos[s[i]] = []
        pos[s[i]].append(i)

    for ch in pos:
        idx = pos[ch]

        # Proceed only if the character 
        # appears more than once
        if len(idx) >= 2:
            first = idx[0]
            last = idx[-1]
            sum_val = 0

            # Compute ASCII sum of characters strictly 
            # between first and last occurrence
            for i in range(first + 1, last):
                sum_val += ord(s[i])
            if sum_val !=0:
                result.append(sum_val)
                
    return result


if __name__ == "__main__":
    
    s = "abacab"
    
    result = asciirange(s)
    result.sort()
    for val in result:
        if val != 0:
            print(val, end=' ')
C#
using System;
using System.Collections.Generic;

class GfG {
    public static List<int> asciirange(string s) {
        
        // Store positions of each character
        Dictionary<char, List<int>> pos =
                new Dictionary<char, List<int>>();
        List<int> result = new List<int>();

        // Track all occurrences of each character
        for (int i = 0; i < s.Length; i++) {
            char ch = s[i];
            if (!pos.ContainsKey(ch)) {
                pos[ch] = new List<int>();
            }
            pos[ch].Add(i);
        }

        foreach (var entry in pos) {
            List<int> idx = entry.Value;

            // Proceed only if the character 
            // appears more than once
            if (idx.Count >= 2) {
                int first = idx[0];
                int last = idx[idx.Count - 1];
                int sum = 0;

                // Compute ASCII sum of characters strictly 
                // between first and last occurrence
                for (int i = first + 1; i < last; i++) {
                    sum += (int)s[i];
                }
                if(sum != 0){
                    result.Add(sum);
                }
            }
        }

        return result;
    }

    static void Main() {
        
        string s = "abacab";
        List<int> result = asciirange(s);
        result.Sort();

        foreach (int val in result) {
            if (val != 0) {
                Console.Write(val + " ");
            }
        }
    }
}
JavaScript
function asciirange(s) {
    
    // Store positions of each character
    const pos = {};
    const result = [];

    // Track all occurrences of each character
    for (let i = 0; i < s.length; i++) {
        const ch = s[i];
        if (!pos[ch]) {
            pos[ch] = [];
        }
        pos[ch].push(i);
    }

    for (const ch in pos) {
        const idx = pos[ch];

        // Proceed only if the character 
        // appears more than once
        if (idx.length >= 2) {
            const first = idx[0];
            const last = idx[idx.length - 1];
            let sum = 0;

            // Compute ASCII sum of characters strictly 
            // between first and last occurrence
            for (let i = first + 1; i < last; i++) {
                sum += s.charCodeAt(i);
            }
            if(sum !== 0){
                result.push(sum);
            }
        }
    }

    return result;
}

// Driver Code
const s = "abacab";

const result = asciirange(s);
result.sort((a, b) => a - b);

for (let i = 0; i < result.length; i++) {
    if (result[i] !== 0) {
        process.stdout.write(result[i] + " ");
    }
}

Output
293 294 

Time Complexity: O(n) where n is the length of string. Note that result vector will be of size 26 so ignore 26*log(26) while sorting.
Auxiliary space: O(n) storing the positions of each characters.

[Approach 2] Using Prefix Sum - O(n) Time and O(n) Space

The idea is to use prefix sums to quickly calculate the ASCII values between the first and last occurrences of each character in the string. We track these positions for each character, and use a prefix sum array to get the range sum in constant time. Only non-zero sums are collected. This makes the approach both efficient and easy to follow.

C++
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

vector<int> asciirange(string &s) {
    int n = s.size();
    vector<int> pref(n + 1);
    vector<int> v[26];

    // Prefix sum and tracking first/last occurrences
    for (int i = 1; i <= n; ++i) {
        int idx = s[i - 1] - 'a';
        if (v[idx].empty()) {
            // first occurrence
            v[idx].push_back(i);
            // initially same as first
            v[idx].push_back(i);
        } else {
            // update last occurrence
            v[idx][1] = i;
        }
        // ASCII prefix sum
        pref[i] = pref[i - 1] + s[i - 1];
    }

    vector<int> ans;
    for (int i = 0; i < 26; ++i) {
        if (!v[i].empty()) {
            int fi = v[i][0], se = v[i][1];
            if (fi != se) {
                int sum = pref[se - 1] - pref[fi];
                if (sum != 0)
                    ans.push_back(sum);
            }
        }
    }

    return ans;
}

int main() {
    string s = "abacab";
    vector<int> result = asciirange(s);
    sort(result.begin(), result.end());

    for (int val : result) {
        cout << val << " ";
    }

    return 0;
}
Java
import java.util.ArrayList;
import java.util.Collections;

class GFG {

    public static ArrayList<Integer> asciirange(String s) {
        int n = s.length();
        int[] pref = new int[n + 1];
        ArrayList<Integer>[] v = new ArrayList[26];

        // Initialize lists
        for (int i = 0; i < 26; ++i) {
            v[i] = new ArrayList<>();
        }

        // Prefix sum and tracking first/last occurrences
        for (int i = 1; i <= n; ++i) {
            int idx = s.charAt(i - 1) - 'a';
            if (v[idx].isEmpty()) {
                // first occurrence
                v[idx].add(i);
                // initially same as first
                v[idx].add(i);
            } else {
                // update last occurrence
                v[idx].set(1, i);
            }
            // ASCII prefix sum
            pref[i] = pref[i - 1] + s.charAt(i - 1);
        }

        ArrayList<Integer> ans = new ArrayList<>();
        for (int i = 0; i < 26; ++i) {
            if (!v[i].isEmpty()) {
                int fi = v[i].get(0), se = v[i].get(1);
                if (fi != se) {
                    int sum = pref[se - 1] - pref[fi];
                    if (sum != 0)
                        ans.add(sum);
                }
            }
        }

        return ans;
    }

    public static void main(String[] args) {
        String s = "abacab";
        ArrayList<Integer> result = asciirange(s);
        Collections.sort(result);

        for (int val : result) {
            System.out.print(val + " ");
        }
    }
}
Python
def asciirange(s):
    n = len(s)
    pref = [0] * (n + 1)
    v = [[] for _ in range(26)]

    # Prefix sum and tracking first/last occurrences
    for i in range(1, n + 1):
        idx = ord(s[i - 1]) - ord('a')
        if not v[idx]:
            # first occurrence
            v[idx].append(i)
            # initially same as first
            v[idx].append(i)
        else:
            # update last occurrence
            v[idx][1] = i
        # ASCII prefix sum
        pref[i] = pref[i - 1] + ord(s[i - 1])

    ans = []
    for i in range(26):
        if v[i]:
            fi, se = v[i][0], v[i][1]
            if fi != se:
                sum_val = pref[se - 1] - pref[fi]
                if sum_val != 0:
                    ans.append(sum_val)

    return ans


if __name__ == "__main__":
    s = "abacab"
    result = asciirange(s)
    result.sort()
    print(*result)
C#
using System;
using System.Collections.Generic;

class GfG
{
    public static List<int> asciirange(string s)
    {
        int n = s.Length;
        int[] pref = new int[n + 1];
        List<int>[] v = new List<int>[26];

        // Initialize lists
        for (int i = 0; i < 26; ++i)
        {
            v[i] = new List<int>();
        }

        // Prefix sum and tracking first/last occurrences
        for (int i = 1; i <= n; ++i)
        {
            int idx = s[i - 1] - 'a';
            if (v[idx].Count == 0)
            {
                // first occurrence
                v[idx].Add(i);
                // initially same as first
                v[idx].Add(i);
            }
            else
            {
                // update last occurrence
                v[idx][1] = i;
            }
            // ASCII prefix sum
            pref[i] = pref[i - 1] + s[i - 1];
        }

        List<int> ans = new List<int>();
        for (int i = 0; i < 26; ++i)
        {
            if (v[i].Count > 0)
            {
                int fi = v[i][0], se = v[i][1];
                if (fi != se)
                {
                    int sum = pref[se - 1] - pref[fi];
                    if (sum != 0)
                        ans.Add(sum);
                }
            }
        }

        return ans;
    }

    static void Main()
    {
        string s = "abacab";
        List<int> result = asciirange(s);
        result.Sort();

        foreach (int val in result)
        {
            Console.Write(val + " ");
        }
    }
}
JavaScript
function asciirange(s) {
    const n = s.length;
    const pref = new Array(n + 1).fill(0);
    const v = Array.from({ length: 26 }, () => []);

    // Prefix sum and tracking first/last occurrences
    for (let i = 1; i <= n; ++i) {
        const idx = s.charCodeAt(i - 1) - 'a'.charCodeAt(0);
        if (v[idx].length === 0) {
            // first occurrence
            v[idx].push(i);
            // initially same as first
            v[idx].push(i);
        } else {
            // update last occurrence
            v[idx][1] = i;
        }
        // ASCII prefix sum
        pref[i] = pref[i - 1] + s.charCodeAt(i - 1);
    }

    const ans = [];
    for (let i = 0; i < 26; ++i) {
        if (v[i].length > 0) {
            const fi = v[i][0], se = v[i][1];
            if (fi !== se) {
                const sum = pref[se - 1] - pref[fi];
                if (sum !== 0) {
                    ans.push(sum);
                }
            }
        }
    }

    return ans;
}

//Driver Code
const s = "abacab";
const result = asciirange(s);
result.sort((a, b) => a - b);
console.log(result.join(" "));

Output
293 294 

[Expected Approach] Space-Optimized Range Sum Using First and Last Indices - O(n) Time and O(1) Space

In this approach, we avoid using extra space like a prefix sum array by directly scanning character ranges when needed. We first record the first and last occurrence of each character using two fixed-size arrays (since there are only 26 lowercase letters). Then, for every character that appears more than once, we compute the sum of ASCII values of characters strictly between its first and last positions by iterating over that range.

C++
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

vector<int> asciirange(string &s) {
    vector<int> result;
    vector<int> first(26, -1);
    vector<int> last(26, -1);
    int n = s.size();

    // Track first and last 
    // occurrence of each character
    for (int i = 0; i < n; i++) {
        if (first[s[i] - 'a'] == -1) {
            first[s[i] - 'a'] = i;
        } else {
            last[s[i] - 'a'] = i;
        }
    }

    // Compute ASCII sums 
    // between first and last occurrence
    for (int i = 0; i < 26; i++) {
        if (first[i] != -1 && last[i] != -1) {
            int sum = 0;
            for (int j = first[i] + 1; j < last[i]; j++) {
                sum += (int)s[j];
            }
            if(sum != 0)
            result.push_back(sum);
        }
    }

    return result;
}

int main() {
    string s = "abacab";

    vector<int> result = asciirange(s);
    sort(result.begin(), result.end());
    
    for (int i = 0; i < result.size(); i++) {
        if (result[i] != 0) {
            cout << result[i] << " ";
        }
    }

    return 0;
}
Java
import java.util.ArrayList;
import java.util.Collections;

class GfG {

    public static ArrayList<Integer> asciirange(String s) {
        ArrayList<Integer> result = new ArrayList<>();
        int[] first = new int[26];
        int[] last = new int[26];
        int n = s.length();

        // Initialize all indices to -1
        for (int i = 0; i < 26; i++) {
            first[i] = -1;
            last[i] = -1;
        }

        // Track first and last 
        // occurrence of each character
        for (int i = 0; i < n; i++) {
            int idx = s.charAt(i) - 'a';
            if (first[idx] == -1) {
                first[idx] = i;
            } else {
                last[idx] = i;
            }
        }

        // Compute ASCII sums 
        // between first and last occurrence
        for (int i = 0; i < 26; i++) {
            if (first[i] != -1 && last[i] != -1) {
                int sum = 0;
                for (int j = first[i] + 1; j < last[i]; j++) {
                    sum += (int) s.charAt(j);
                }
                if(sum != 0){
                result.add(sum);
                }
            }
        }
        
        return result;
    }

    public static void main(String[] args) {
        String s = "abacab";
        
        ArrayList<Integer> result = asciirange(s);
        Collections.sort(result);
        
        for (int val : result) {
            if (val != 0) {
                System.out.print(val + " ");
            }
        }
    }
}
Python
def asciirange(s):
    result = []
    n = len(s)

    # Initialize all indices to -1
    first = [-1] * 26
    last = [-1] * 26

    # Track first and last 
    # occurrence of each character
    for i in range(n):
        idx = ord(s[i]) - ord('a')
        if first[idx] == -1:
            first[idx] = i
        else:
            last[idx] = i

    # Compute ASCII sums 
    # between first and last occurrence
    for i in range(26):
        if first[i] != -1 and last[i] != -1:
            sumval = 0
            for j in range(first[i] + 1, last[i]):
                sumval += ord(s[j])
            if sumval!= 0:
                result.append(sumval)

    # Sort the results in increasing order
    
    return result


if __name__ == "__main__": 
    s = "abacab"
    
    result = asciirange(s)
    result.sort()

    for val in result:
        if val != 0:
            print(val, end=' ')
C#
using System;
using System.Collections.Generic;

class GfG {
    public static List<int> asciirange(string s) {
        List<int> result = new List<int>();
        int[] first = new int[26];
        int[] last = new int[26];
        int n = s.Length;

        // Initialize all indices to -1
        for (int i = 0; i < 26; i++) {
            first[i] = -1;
            last[i] = -1;
        }

        // Track first and last 
        // occurrence of each character
        for (int i = 0; i < n; i++) {
            int idx = s[i] - 'a';
            if (first[idx] == -1)
            {
                first[idx] = i;
            }
            else
            {
                last[idx] = i;
            }
        }

        // Compute ASCII sums 
        // between first and last occurrence
        for (int i = 0; i < 26; i++) {
            if (first[i] != -1 && last[i] != -1) {
                int sum = 0;
                for (int j = first[i] + 1; j < last[i]; j++) {
                    sum += (int)s[j];
                }
                if(sum != 0){
                result.Add(sum);
                }
            }
        }
        
        return result;
    }

    static void Main() {
        string s = "abacab";

        List<int> result = asciirange(s);
        result.Sort();
        
        foreach (int val in result) {
            if (val != 0)
            {
                Console.Write(val + " ");
            }
        }
    }
}
JavaScript
function asciirange(s) {
    const result = [];
    const first = new Array(26).fill(-1);
    const last = new Array(26).fill(-1);
    const n = s.length;

    // Track first and last 
    // occurrence of each character
    for (let i = 0; i < n; i++) {
        const idx = s.charCodeAt(i) - 97;
        if (first[idx] === -1) {
            first[idx] = i;
        } else {
            last[idx] = i;
        }
    }

    // Compute ASCII sums 
    // between first and last occurrence
    for (let i = 0; i < 26; i++) {
        if (first[i] !== -1 && last[i] !== -1) {
            let sum = 0;
            for (let j = first[i] + 1; j < last[i]; j++) {
                sum += s.charCodeAt(j);
            }
            if(sum !== 0){
            result.push(sum);
            }
        }
    }
    
    return result;
}

// Driver Code
const s = "abacab";

const result = asciirange(s);
result.sort((a, b) => a - b);

for (let i = 0; i < result.length; i++) {
    if (result[i] !== 0) {
        process.stdout.write(result[i] + " ");
    }
}

Output
293 294 
Comment