LogIn
I don't have account.

My Teradata SWE Intern Interview Experience (Full Story, Real Code, Real Mistakes)

Janhavi Rajput
30 Views

#interview-experience

#learning-roadmap

#teradata-company

I want to share my Teradata SWE Intern interview experience in a simple and honest way. I made mistakes. The interviewer gave me hints. I fixed my answers live. This is exactly how it happened, round by round, with the real Java code I wrote.

If you are preparing for a Teradata SWE intern interview or any Java + DSA interview, this post will help you know what to expect.

Detail Info
Company Teradata
Role  Software Engineer Intern (SWE Intern)
Number of rounds 2 (both technical)
Round 1 time Around 45 minutes
Round 2 time Around 35–40 minutes
Round 1 topics Java basics, OOP, 2 DSA questions
Round 2 topics 1 design question with 2 follow-ups
Mode Online video call
Result Waiting to hear back

How I Prepared Before the Interview

I got the interview call by email. After that, I had a few days to prepare. Here is what I actually did, not what looks good on paper:

I revised Java basics again, even the topics I thought I already knew well, like strings, OOP and the static keyword. I solved easy and medium DSA problems on LeetCode, focusing on patterns like stacks, hashmaps and arrays, instead of solving random problems with no pattern. I also read a little about how java.util.Random works internally, just out of curiosity and that one small habit helped me a lot in Round 2 more on that later.

I was still nervous before the call. I think everyone is, no matter how much you prepare.

Round 1: Java, OOP and Two DSA Questions (About 45 Minutes)

The interviewer started with simple, friendly questions and then slowly went deeper. This is common in most interviews, so don't let the easy start make you relax too much.

Question 1: How Do Strings Work in Java?

He first asked me how strings work in Java. I explained the string pool. In simple words, when you create a string using double quotes, like "hello", Java stores it in a special memory area called the string pool. If you create the same string again, Java does not make a new one. It just reuses the old one. This saves memory.

Then he asked the real question: why are strings immutable in Java?

This is where I paused for a second. I gave more than one reason, because one reason is not enough for this question:

  1. If strings could change, the string pool would break, because many variables share the same string object.
  2. Strings hold sensitive data like file paths and class names, so keeping them fixed keeps the code safer.
  3. Since a string never changes, many threads can use it at the same time with no risk.
  4. Java saves the hash code of a string the first time it is calculated and this only works because the string never changes later.

He seemed happy that I gave more than one reason instead of just one line.

Question 2: Pass by Value or Pass by Reference?

Next, he asked about pass by value and pass by reference in Java. And here is my first small mistake.

I said, "Primitives are pass by value and objects are pass by reference." This is a very common answer and also a wrong one. He asked me a simple follow-up: "If it is pass by reference, why can't I change what the caller's variable points to from inside a method?" That one question made me stop and think again.

I then corrected myself. Java is always pass by value. For objects, the value being copied is the reference itself, not the object. So if I change the object using that reference inside a method, the caller sees the change. But if I point the reference to a new object inside the method, the caller's original variable does not change at all.

Mistake: I called it "pass by reference" for objects. Hint he gave: He asked why reassigning inside a method does not affect the caller. How I fixed it: I understood that only the reference value is copied, not the object, so reassigning the copy never touches the original.

Question 3: Polymorphism and the static Keyword

He asked me to explain compile time and runtime polymorphism.

I said compile time polymorphism is method overloading. Same method name, different parameters and the compiler decides which one to call before the program even runs.

Runtime polymorphism is method overriding. A child class gives its own version of a parent class method and Java decides which version to run based on the actual object, not the type of the variable. I also mentioned that Java uses something called a vtable internally to pick the correct method at runtime.

Then he asked about the static keyword. I explained that static variables belong to the class, not one object. Static methods can be called without creating an object. I also added that static methods cannot use this, because there is no specific object attached to them.

He asked one small follow-up here: "Can a static method be overridden?" I said no and explained that static methods are linked at compile time, not runtime, because there is only one version of them, so there is nothing to decide at runtime. He nodded and we moved to coding.

DSA Question 1: Valid Parentheses

Link: Valid Parentheses

The question: check if a string made only of ()[]{} has all brackets matched and in the right order.

My first idea (wrong): My first thought was simple just count the number of opening brackets and closing brackets. If they are equal, the string is valid.

I said this out loud and he asked me to test it on ")(" and "([)]". I tried it in my head and realized both have equal opening and closing brackets, but both are actually invalid. My counting idea does not check the order of brackets, only the total count. That was my mistake and his question helped me see it myself.

Fixing it brute force way I thought of next: I thought about repeatedly scanning the string and removing pairs like "()", "[]", "{}" whenever they appear next to each other and repeating this until nothing changes. If the string becomes empty at the end, it is valid. This works, but it can take many passes over the string, so it is slower than needed, close to O(n²) in bad cases.

Optimal solution using a stack: Then I moved to the correct and efficient idea: use a stack. Every time I see an opening bracket, I push it. Every time I see a closing bracket, I pop the top of the stack and check if it matches. If the stack is empty when I need to pop or the bracket does not match, the string is invalid. At the end, the stack must be empty.

import java.util.*;

public class ValidParentheses {
    public static boolean isValid(String s) {
        Deque<Character> stack = new ArrayDeque<>();
        Map<Character, Character> pairs = Map.of(')', '(', ']', '[', '}', '{');

        for (char c : s.toCharArray()) {
            if (pairs.containsValue(c)) {
                stack.push(c);
            } else if (pairs.containsKey(c)) {
                if (stack.isEmpty() || stack.pop() != pairs.get(c)) {
                    return false;
                }
            }
        }
        return stack.isEmpty();
    }
}

This runs in O(n) time and uses O(n) space in the worst case. I ran it on ")(" and "([)]" and this time it correctly returned false for both.

Follow-up question he asked: "Can you solve this without using extra space?" My answer: I said not really, not for the general case, because we need some way to remember which bracket is still open and waiting to be closed and a stack (or something acting like one) is the simplest way to do that. He agreed and said that's the expected answer.

DSA Question 2: First Unique Character in a String

Link: First Unique Character in a String

The question: find the index of the first character in a string that appears only once. Return -1 if there is none.

My first idea (brute force): For every character, check the whole string again to see how many times it appears. If it appears only once, return its index.

public static int firstUniqCharBruteForce(String s) {
    for (int i = 0; i < s.length(); i++) {
        boolean isUnique = true;
        for (int j = 0; j < s.length(); j++) {
            if (i != j && s.charAt(i) == s.charAt(j)) {
                isUnique = false;
                break;
            }
        }
        if (isUnique) return i;
    }
    return -1;
}

This works fine and I said it out loud first, being honest that it is O(n²) because of the two loops inside each other. He asked, "Can we do better?" That was the hint I needed.

Optimal solution: I count how many times each character appears first, in one pass. Then I go through the string a second time, in order and return the first character whose count is exactly 1.

public class FirstUniqueChar {
    public static int firstUniqChar(String s) {
        int[] freq = new int[26];
        for (char c : s.toCharArray()) {
            freq[c - 'a']++;
        }
        for (int i = 0; i < s.length(); i++) {
            if (freq[s.charAt(i) - 'a'] == 1) {
                return i;
            }
        }
        return -1;
    }
}

This is O(n) time and O(1) space, since the array size is fixed at 26 for lowercase letters. Both versions gave the same answer on test strings like "leetcode" (answer 0) and "loveleetcode" (answer 2), so I could show him the brute force and the fast version give the same result, just at different speeds.

Follow-up question he asked: "What if the string has uppercase letters and numbers too, not just lowercase letters?" My answer: I said I would use a HashMap<Character, Integer> instead of a fixed size array, since we can no longer assume only 26 lowercase letters. The logic stays the same, just the storage changes.

Round 1 Follow-Up Questions (Quick List)

  • Can Valid Parentheses be solved without extra space? → No, not in the general case, since we need to track open brackets somehow.
  • Can a static method be overridden? → No, because static methods use compile-time binding, not runtime.
  • What if the input has uppercase letters or digits in the unique character question? → Use a HashMap instead of a fixed array.
  • Why does a == b work for two string literals but not for new String()? → Literals share the same pooled object; new String() always creates a new object on the heap.

Round 1 ended after about 45 minutes. I felt okay, not perfect, because of my pass-by-reference slip, but I was happy I caught my own mistake in the parentheses question before he had to point it out fully.

Round 2: The Design Round (About 60-70 Minutes)

This round had only one main question, but it had layers, like an onion. Every time I solved one part, he added a new twist.

Main Question: Design Insert, Delete, Search and GetRandom, All in O(1) Average Time

Link: Insert Delete GetRandom O(1)

No duplicate values allowed.

Step 1 my first idea (too slow): I said I could just use a normal list (ArrayList). Insert means adding to the list. Search means checking if the value is already there. Delete means finding and removing it.

class NaiveRandomizedSet {
    private List<Integer> values = new ArrayList<>();
    private Random rand = new Random();

    public boolean insert(int val) {
        if (values.contains(val)) return false; // O(n) search
        values.add(val);
        return true;
    }

    public boolean remove(int val) {
        return values.remove(Integer.valueOf(val)); // O(n) search + shift
    }

    public int getRandom() {
        return values.get(rand.nextInt(values.size())); // this part is already O(1)
    }
}

He asked me right away: "What is the time to search in this list?" I said O(n) and I could see that this was not going to be good enough. This was the hint that told me I needed something faster than a plain list for search and delete.

Step 2 adding a HashMap (getting closer, but still a mistake left): I added a HashMap<Integer, Integer> that maps each value to its index inside the list. Now search is O(1), because I can just check the map. But I made a second mistake here I still removed the value from the middle of the list using list.remove(index) directly, which shifts every element after it, so delete was still O(n) even though search was now O(1).

He asked, "What is the time complexity of removing from the middle of an ArrayList?" That question made me realize my delete was still slow, even though I felt like I had already solved the hard part.

Step 3 the actual optimal solution: The fix is simple once you see it: instead of removing from the middle, swap the value I want to remove with the last value in the list, update the map for the value that moved and then just delete the last position, which is fast on an ArrayList.

import java.util.*;

public class RandomizedSet {
    private final Map<Integer, Integer> valueToIndex;
    private final List<Integer> values;
    private final Random rand = new Random();

    public RandomizedSet() {
        valueToIndex = new HashMap<>();
        values = new ArrayList<>();
    }

    public boolean insert(int val) {
        if (valueToIndex.containsKey(val)) return false;
        valueToIndex.put(val, values.size());
        values.add(val);
        return true;
    }

    public boolean remove(int val) {
        if (!valueToIndex.containsKey(val)) return false;

        int idxToRemove = valueToIndex.get(val);
        int lastVal = values.get(values.size() - 1);

        values.set(idxToRemove, lastVal);
        valueToIndex.put(lastVal, idxToRemove);

        values.remove(values.size() - 1);
        valueToIndex.remove(val);
        return true;
    }

    public int getRandom() {
        return values.get(rand.nextInt(values.size()));
    }
}

Now insert, remove and getRandom are all O(1) on average. I explained each step out loud while writing it, which I think helped the interviewer follow my thinking, even before I finished typing the code.

Follow-Up 1: "How Would You Build Random Yourself?"

He then asked something I did not expect at first: "If you did not have Java's Random class, how would you generate a random number yourself?"

My mistake: My first answer was, "I would use the current time in milliseconds and take it mod the bound." I said this quickly, thinking it sounded smart. He simply asked me to call it twice, right after each other and check the result.

static int badRandom(int bound) {
    return (int) (System.currentTimeMillis() % bound);
}

When I actually thought this through, I realized that if this method is called many times very fast, the clock value barely changes between calls, so I can get the same number again and again. That is a bad random number generator, since real random numbers should not repeat like that so easily. This was a clear hint from him, without him telling me the answer directly.

How I fixed it: I explained a Linear Congruential Generator or LCG for short. It keeps its own internal number (called a seed) and updates it every time using a formula: seed = (a * seed + c) mod m. This does not depend on the clock at all, it depends only on its own last value, so calling it many times fast still gives different-looking numbers.

public class MyRandom {
    private static final long A = 0x5DEECE66DL;
    private static final long C = 0xBL;
    private static final long MASK = (1L << 48) - 1;

    private long seed;

    public MyRandom(long seed) {
        this.seed = (seed ^ A) & MASK;
    }

    public MyRandom() {
        this(System.nanoTime());
    }

    private int next(int bits) {
        seed = (seed * A + C) & MASK;
        return (int) (seed >>> (48 - bits));
    }

    public int nextInt(int bound) {
        if (bound <= 0) throw new IllegalArgumentException("bound must be positive");

        if ((bound & -bound) == bound) {
            return (int) ((bound * (long) next(31)) >> 31);
        }

        int bits, val;
        do {
            bits = next(31);
            val = bits % bound;
        } while (bits - val + (bound - 1) < 0);
        return val;
    }
}

I also mentioned that this is close to how java.util.Random actually works inside Java, which I had read about while preparing. I could tell that small bit of extra knowledge made a good impression.

Follow-up he added on top of this: "Does bits % bound give a perfectly equal chance to every number?" My answer: I said no, not always. If the bound does not divide evenly into the generator's output range, some numbers can come up slightly more often than others. The fix is to throw away a result and try again in the rare case it falls in the unfair range, instead of just using it directly. He said that was exactly the kind of detail he wanted to hear.

Follow-Up 2: "Now Allow Duplicate Values"

The last twist: "Redesign this so the same value can be added more than once and getRandom should still be fair."

My mistake here: My first idea was to just keep a count of how many times each value was inserted, using HashMap<Integer, Integer> for counts. But when he asked, "If a value is stored 3 times in your list and you want to remove just one of them, how do you know which index to remove?", I realized a simple count does not tell me anything about where those copies are sitting in the list.

Fixing it the correct idea: Instead of one index or one count per value, I store a set of indexes for each value, meaning every position in the list where that value currently sits.

import java.util.*;

public class RandomizedCollection {
    private final Map<Integer, Set<Integer>> valueToIndices;
    private final List<Integer> values;
    private final Random rand = new Random();

    public RandomizedCollection() {
        valueToIndices = new HashMap<>();
        values = new ArrayList<>();
    }

    public boolean insert(int val) {
        valueToIndices.computeIfAbsent(val, k -> new HashSet<>()).add(values.size());
        values.add(val);
        return valueToIndices.get(val).size() == 1;
    }

    public boolean remove(int val) {
        Set<Integer> indices = valueToIndices.get(val);
        if (indices == null || indices.isEmpty()) return false;

        int idxToRemove = indices.iterator().next();
        int lastIndex = values.size() - 1;
        int lastVal = values.get(lastIndex);

        indices.remove(idxToRemove);

        if (idxToRemove != lastIndex) {
            values.set(idxToRemove, lastVal);
            valueToIndices.get(lastVal).remove(lastIndex);
            valueToIndices.get(lastVal).add(idxToRemove);
        }

        values.remove(lastIndex);
        if (indices.isEmpty()) valueToIndices.remove(val);
        return true;
    }

    public int getRandom() {
        return values.get(rand.nextInt(values.size()));
    }
}

The nice part, which I said out loud and I think he liked, is that getRandom does not need any change at all. If a value sits in the list 3 times, it naturally has 3 chances out of the total, so it is picked more often automatically, just because it takes up more space in the list.

Round 2 Follow-Up Questions (Quick List)

  • Why is a plain ArrayList not enough for O(1) search? → Because searching means checking every item one by one, which is O(n).
  • What is the time cost of removing from the middle of an ArrayList? → O(n), because every item after it has to shift left.
  • Why is System.currentTimeMillis() a bad random number source when called fast? → The value barely changes between very close calls, so you can get the same or a very close number again.
  • Does value % bound always give a fair, equal chance? → No, it can be slightly unfair if bound does not divide evenly into the generator's range, so a retry step is used to fix this.
  • Why does getRandom not need any change for duplicate values? → Because each copy of a value takes its own slot in the list, so the random pick is already naturally fair.

Round 2 ended after about 60 to 70 minutes, it felt more intense because of how many follow-ups came one after another.

Mistakes I Made and What I Learned From Them

Looking back, my mistakes were not silly typing errors. They were small gaps in how deeply I understood things I thought I already knew well:

I said "objects are pass by reference," which is a very common wrong belief and I only fixed it when he asked a simple counter question. I said bracket matching can be solved just by counting and testing it myself on ")(" showed me it was wrong. I removed from the middle of a list without thinking about the shifting cost, even after I had already added a HashMap. I trusted the system clock as a source of randomness, without thinking about how fast a computer can call a method.

The pattern I noticed is this: the interviewer almost never told me I was wrong directly. He asked a small question and that question made me test my own idea and find the mistake myself. I think that is actually a good sign about how the interview was run and it is something to expect in your own interview too.

My Preparation Tips for Teradata SWE Intern Interview

If you are getting ready for a similar interview, here is what I would tell my past self:

  • Do not just memorize definitions like "strings are immutable." Ask yourself why and try to list more than one reason, because interviewers often ask "why" right after you give the "what."

  • Do not say "objects are pass by reference" in Java. Practice explaining it correctly out loud until it feels natural, not memorized.

  • When you solve a DSA problem, say your first idea out loud, even if it is a slow brute force one. Interviewers like to see how you improve it step by step, not just the final fast answer appearing from nowhere.

  • Test your own idea with a tricky example before the interviewer has to point it out. For Valid Parentheses, testing ")(" or "([)]" yourself can catch a wrong idea early.

  • For design questions, think in layers: first make it work, then make it fast for search, then make it fast for delete, then handle random access. Most design interviews are built exactly in this step-by-step way.

  • Read a little about how basic library functions work internally, like Random, HashMap or ArrayList. It does not take long and it can turn a normal answer into a strong one.

  • Stay calm when you get a follow-up question. A follow-up usually does not mean you are wrong. It often just means the interviewer wants to see how deep your understanding goes.

Final Thoughts

This Teradata SWE intern interview experience taught me more than most college assignments. Round 1 tested if I really understood the basics, not just the definitions. Round 2 tested if I could build something and then improve it live, step by step, when someone points out a weak spot.

I am still waiting for the final result while writing this. But whatever happens, I already feel like a better developer after going through both rounds. I hope this real, honest interview experience helps you prepare better for your own Teradata interview or any similar Java and DSA interview.

Frequently Asked Questions (FAQ)

Q: How many rounds are there in the Teradata SWE intern interview?

A: In my case, there were 2 technical rounds. Round 1 covered Java basics, OOP and 2 DSA questions. Round 2 was a single design question with follow-up questions.

Q: What DSA questions are asked in the Teradata SWE intern interview?

A: I was asked Valid Parentheses and First Unique Character in a String in Round 1 and an Insert-Delete-GetRandom O(1) design question in Round 2, with follow-ups on building a random number generator and supporting duplicate values.

Q: Does Teradata ask Java OOP questions for SWE intern roles?

A: Yes. I was asked about string immutability, pass by value vs pass by reference, compile-time vs runtime polymorphism and the static keyword.

Q: How long does the Teradata SWE intern interview take?

A: My Round 1 took about 45 minutes and Round 2 took about 60 to 70 minutes.

Q: Is the Teradata SWE intern interview hard?

A: It is not extremely hard, but it goes deep on basics. Simple-sounding questions often have a tricky follow-up, so understanding the "why" behind Java concepts matters more than just knowing the "what."

Q: How should I prepare for a Teradata SWE intern interview?

A: Revise Java fundamentals with a focus on the reasoning behind them, practice common DSA patterns like stacks and hashmaps and practice explaining your thought process out loud, from a brute force idea to an optimal one.

Responses (0)

Write a response

CommentHide Comments

No Comments yet.