
Submit your resume via the PayPal Careers website or job platforms like LinkedIn.
Tailor your resume to match the job description, especially highlighting relevant skills and experience.
A recruiter will contact you for an initial phone screen.
Expect general questions about your background, availability, salary expectations, and interest in the role.
If you're applying for a technical role (like software engineering), this stage includes:
Online coding test (platforms like HackerRank or Codility)
Questions on data structures, algorithms, and sometimes system design
For non-tech roles (marketing, finance, etc.):
Situational and behavioral questions
Role-specific knowledge assessments
Usually involves 3–5 rounds:
Technical rounds (coding, problem-solving)
System design (for experienced roles)
Behavioral interviews using the STAR method
Culture fit and PayPal’s core values
You may also be given case studies or scenario-based tasks depending on the role.
Interview with a hiring manager or director-level person
Focuses on long-term goals, team fit, and deeper role expectations
If selected, PayPal extends an offer (sometimes negotiable).
Background check, reference verification, and official documentation follow.
To remove duplicate nodes from an unsorted linked list, you typically use a hash set to track which values you've already seen. Here's the general idea:
Traverse the linked list.
For each node, check if its value is in the hash set:
If it is, remove the node (adjust pointers).
If it isn’t, add the value to the hash set.
Here’s a simple Python implementation:
class Node:
def __init__(self, data):
self.data = data
self.next = None
def remove_duplicates(head):
if head is None:
return None
seen = set()
current = head
prev = None
while current:
if current.data in seen:
# Duplicate found: skip the current node
prev.next = current.next
else:
seen.add(current.data)
prev = current
current = current.next
return head
# Helper function to print the list
def print_list(head):
current = head
while current:
print(current.data, end=" -> ")
current = current.next
print("None")
# Example usage
head = Node(10)
head.next = Node(20)
head.next.next = Node(10)
head.next.next.next = Node(30)
head.next.next.next.next = Node(20)
print("Original list:")
print_list(head)
head = remove_duplicates(head)
print("\nList after removing duplicates:")
print_list(head)
Output:
Original list:
10 -> 20 -> 10 -> 30 -> 20 -> None
List after removing duplicates:
10 -> 20 -> 30 -> None
Finding the length of a singly linked list is pretty straightforward:
Start at the head.
Traverse each node, counting as you go.
When you reach the end (None), the counter will give you the length.
Here’s a simple Python function:
class Node:
def __init__(self, data):
self.data = data
self.next = None
def get_length(head):
count = 0
current = head
while current:
count += 1
current = current.next
return count
# Helper function to create and print the list
def print_list(head):
current = head
while current:
print(current.data, end=" -> ")
current = current.next
print("None")
# Example usage
head = Node(1)
head.next = Node(2)
head.next.next = Node(3)
head.next.next.next = Node(4)
print("Linked List:")
print_list(head)
length = get_length(head)
print(f"\nLength of the linked list: {length}")
Output:
Linked List:
1 -> 2 -> 3 -> 4 -> None
Length of the linked list: 4
To find the third node from the end of a singly linked list, there are two common ways:
Simple way (two passes):
Find the length of the list.
Traverse again to (length - 3)-th node.
Better way (one pass using two pointers):
Move the first pointer three steps ahead.
Then move both pointers one step at a time.
When the first pointer reaches the end, the second pointer will be at the third node from the end.
Here’s the one-pass Python solution:
class Node:
def __init__(self, data):
self.data = data
self.next = None
def third_from_end(head):
first = head
second = head
# Move first pointer 3 steps ahead
for _ in range(3):
if not first:
return None # Less than 3 nodes
first = first.next
# Move both pointers until first reaches the end
while first:
first = first.next
second = second.next
return second
# Helper function to print the list
def print_list(head):
current = head
while current:
print(current.data, end=" -> ")
current = current.next
print("None")
# Example usage
head = Node(5)
head.next = Node(10)
head.next.next = Node(15)
head.next.next.next = Node(20)
head.next.next.next.next = Node(25)
print("Linked List:")
print_list(head)
node = third_from_end(head)
if node:
print(f"\nThird node from end: {node.data}")
else:
print("\nThe linked list has less than 3 nodes.")
Output:
Linked List:
5 -> 10 -> 15 -> 20 -> 25 -> None
Third node from end: 15
In postorder traversal, for each node you visit left → right → root.
This is commonly used in trees (especially binary trees).
Here’s a simple recursive Python implementation for postorder traversal:
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def postorder_traversal(root):
if root is None:
return
# Traverse the left subtree
postorder_traversal(root.left)
# Traverse the right subtree
postorder_traversal(root.right)
# Visit the root
print(root.data, end=" ")
# Example usage
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.left.left = Node(4)
root.left.right = Node(5)
print("Postorder traversal:")
postorder_traversal(root)
Output:
4 5 2 3 1
Explanation:
First go all the way left (4),
Then right (5),
Then parent (2),
Then right subtree (3),
Finally root (1).
If you have an array of integers from 1 to 100 but one number is missing, the classic way to find it is:
* Calculate the expected sum of numbers from 1 to 100.
* Calculate the actual sum of the array.
* The missing number = expected sum - actual sum.
Here’s a clean Python solution:
def find_missing_number(arr):
n = 100
expected_sum = n * (n + 1) // 2 # Sum of first n natural numbers
actual_sum = sum(arr)
return expected_sum - actual_sum
# Example usage
arr = list(range(1, 101))
arr.remove(45) # Suppose 45 is missing
missing = find_missing_number(arr)
print(f"The missing number is: {missing}")
Output:
The missing number is: 45
Quick math reminder:
Sum of first n numbers = n(n+1)/2
Given data about tennis players (say wins, losses, points, or matches played), rank the players.
Idea:
Typically in sports, players are ranked based on:
Points (higher points = better ranking)
If points are tied → Wins could be a tie-breaker
If still tied → Maybe head-to-head record, etc.
Plan:
Parse the data into player objects (with fields like name, points, wins, etc.).
Sort the players by:
First, by points (descending),
Then, by wins (descending), if points are tied.
Output the sorted list as rankings.
Here’s a simple Python algorithm:
class Player:
def __init__(self, name, points, wins):
self.name = name
self.points = points
self.wins = wins
def rank_players(players):
# Sort players: first by points descending, then by wins descending
players.sort(key=lambda p: (-p.points, -p.wins))
return players
# Example usage
players = [
Player("Novak Djokovic", 12000, 75),
Player("Carlos Alcaraz", 11500, 70),
Player("Daniil Medvedev", 11500, 72),
Player("Jannik Sinner", 11000, 68)
]
ranked_players = rank_players(players)
print("Player Rankings:")
for i, player in enumerate(ranked_players, start=1):
print(f"{i}. {player.name} - Points: {player.points}, Wins: {player.wins}")
Output:
Player Rankings:
1. Novak Djokovic - Points: 12000, Wins: 75
2. Daniil Medvedev - Points: 11500, Wins: 72
3. Carlos Alcaraz - Points: 11500, Wins: 70
4. Jannik Sinner - Points: 11000, Wins: 68
Key notes:
-p.points because we want highest points first (descending).
-p.wins to break ties if two players have the same points.
function greeting(name) {
alert('Hello ' + name);
}
function processUserInput(callback) {
var name = prompt('Enter the name here.');
callback(name);
}
processUserInput(greeting); Node.js is a runtime environment that lets you run JavaScript outside the browser.
Built on Chrome's V8 engine (super fast JavaScript engine).
It's event-driven, non-blocking, and asynchronous — perfect for scalable network apps.
It lets you build server-side applications using JavaScript!
* Think of it like: "Instead of using JavaScript only to make websites interactive (frontend), now you can also build servers, APIs, backends, tools, etc. with it."
| Use Case | Example |
|---|---|
| Web Servers | Create APIs for websites, apps (Express.js is famous) |
| Backend for Mobile Apps | Handle requests from mobile apps (iOS/Android) |
| Real-Time Apps | Chat apps, gaming servers (Socket.IO, WebSockets) |
| Streaming Services | Netflix, YouTube streaming parts |
| File System Utilities | Scripts to automate tasks (read/write files) |
| E-commerce APIs | Shopping carts, user management, orders, etc. |
| Command Line Tools | Build CLI apps like project generators |
| Microservices | Lightweight, fast microservice backends |
Netflix
Uber
PayPal
Walmart
NASA (yes, even NASA!)
Same language everywhere (frontend + backend = JavaScript ❤️).
Huge ecosystem (thanks to npm, the Node package manager).
Fast, scalable, lightweight.
Python program to arrange numbers from 1 to 100 in a perfect triangle. A perfect triangle in this context means a triangular arrangement where each row has one more number than the previous row.
Here's the Python code to achieve this:
def perfect_triangle(n):
"""Arranges numbers from 1 to n in a perfect triangle.
Args:
n: The total number of elements to arrange.
"""
numbers = list(range(1, n + 1))
num_rows = 0
count = 0
while count < n:
num_rows += 1
count += num_rows
if count > n:
num_rows -= 1
index = 0
for i in range(1, num_rows + 1):
row = numbers[index : index + i]
print(" ".join(map(str, row)).center(num_rows * 3)) # Adjust spacing as needed
index += i
# Arrange numbers from 1 to 100
perfect_triangle(100)
Explanation:
perfect_triangle(n) Function:
n as input, representing the total number of numbers to arrange.numbers containing integers from 1 to n.num_rows needed for the perfect triangle. It iteratively adds the row number to the count until count exceeds n. If it exceeds, it decrements num_rows by 1 to fit within the n numbers.index to keep track of the current position in the numbers list.1 to num_rows (inclusive), representing each row of the triangle.numbers list to get the elements for the current row. The number of elements in each row i increases by one." ".join(map(str, row)) converts the numbers in the row to strings and joins them with spaces..center(num_rows * 3) centers the row of numbers. The num_rows * 3 is a rough estimate for the total width needed to center the largest row; you might need to adjust this value based on the number of rows for better visual centering.index is updated to point to the start of the next row in the numbers list.Calling the Function:
perfect_triangle(100) calls the function to arrange numbers from 1 to 100 in the perfect triangle format.How it determines the number of rows:
A perfect triangle with k rows contains 1 + 2 + 3 + ... + k = k * (k + 1) / 2 numbers. The code iteratively finds the largest num_rows such that the sum of numbers from 1 to num_rows is less than or equal to n.
Output:
When you run this code, you'll see the numbers from 1 to (the largest triangular number less than or equal to 100, which is 1 + 2 + ... + 13 = 91) arranged in a triangular pattern:
1
2 3
4 5 6
7 8 9 10
11 12 13 14 15
16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 32 33 34 35 36
37 38 39 40 41 42 43 44 45
46 47 48 49 50 51 52 53 54 55
56 57 58 59 60 61 62 63 64 65 66
67 68 69 70 71 72 73 74 75 76 77 78
79 80 81 82 83 84 85 86 87 88 89 90 91
The numbers from 92 to 100 will not be included in this perfect triangular arrangement as they would form an incomplete next row.
a core concept in Object-Oriented Programming (OOP)! While the terms "dynamic polymorphism" and "runtime polymorphism" are often used interchangeably, they essentially refer to the same mechanism: the ability of a single interface (like a method name) to represent different underlying forms (different implementations) at runtime.
Let's break it down with explanations and examples in Python:
Understanding Runtime Polymorphism (or Dynamic Polymorphism):
Runtime polymorphism means that the specific method or function that will be executed is not determined until the program is running (at runtime). This decision is based on the actual type (class) of the object being referred to, not the type of the reference variable.
To achieve runtime polymorphism, you typically need two key elements:
How it Works:
When you call a method on an object through a base class reference, the runtime environment (like the Python interpreter) checks the actual type of the object in memory. It then executes the version of the method that is defined in the object's class, even if the reference is of the base class type. This is also known as dynamic method dispatch or late binding.
Example in Python:
class Animal:
def speak(self):
print("Generic animal sound")
class Dog(Animal):
def speak(self):
print("Woof!")
class Cat(Animal):
def speak(self):
print("Meow!")
# Creating instances of the derived classes
dog = Dog()
cat = Cat()
# Treating them through a common base class reference (implicitly in Python)
animals = [dog, cat]
# Calling the 'speak' method on each object
for animal in animals:
animal.speak()
Output:
Woof!
Meow!
Explanation of the Example:
Animal with a speak() method.Dog and Cat, which override the speak() method to provide their specific sounds.Dog and Cat.animals containing these objects. Even though we are treating them as Animal objects (implicitly, as Python is dynamically typed), when we call animal.speak(), the runtime environment determines the actual type of the object (Dog or Cat) and executes the corresponding overridden speak() method.
Why is this useful?
Encapsulation, Association, and Aggregation in Java with clear explanations and examples.
1. Encapsulation:
Concept: Encapsulation is the mechanism of wrapping data (variables) and the code (methods) that operates on the data into a single unit (a class). It also involves controlling the access to the internal data of an object, often using access modifiers. Think of it like a protective shield around the data.
Goals of Encapsulation:
Implementation in Java:
private.getter methods to access the data (in a controlled way).setter methods to modify the data (often with validation logic).Example:
public class BankAccount {
private String accountNumber; // Private data
private double balance; // Private data
public BankAccount(String accountNumber, double initialBalance) {
this.accountNumber = accountNumber;
this.balance = initialBalance;
}
// Public getter for accountNumber
public String getAccountNumber() {
return accountNumber;
}
// Public getter for balance
public double getBalance() {
return balance;
}
// Public method to deposit money
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.println("Deposited: " + amount);
} else {
System.out.println("Invalid deposit amount.");
}
}
// Public method to withdraw money
public void withdraw(double amount) {
if (amount > 0 && balance >= amount) {
balance -= amount;
System.out.println("Withdrawn: " + amount);
} else {
System.out.println("Insufficient funds or invalid withdrawal amount.");
}
}
// No direct access to accountNumber or balance from outside
}
public class Main {
public static void main(String[] args) {
BankAccount myAccount = new BankAccount("12345", 1000.0);
System.out.println("Account Number: " + myAccount.getAccountNumber());
System.out.println("Current Balance: " + myAccount.getBalance());
myAccount.deposit(500.0);
myAccount.withdraw(200.0);
// myAccount.balance = -500; // This would be illegal due to private access
}
}
In this example, accountNumber and balance are private. We can only access and modify them through the public methods getAccountNumber(), getBalance(), deposit(), and withdraw(), which allows us to control how the data is used and ensures data integrity (e.g., preventing negative deposits).
2. Association:
Concept: Association represents a "uses-a" or "has-a" relationship between two separate classes. It signifies a general connection between objects of these classes. The association doesn't imply any strong ownership or lifecycle dependency between the objects. The associated objects can exist independently.
Types of Association (based on multiplicity):
Implementation in Java:
Example (One-to-One):
class Person {
private String name;
private Passport passport; // Association with Passport
public Person(String name) {
this.name = name;
}
public void assignPassport(Passport passport) {
this.passport = passport;
}
public Passport getPassport() {
return passport;
}
public String getName() {
return name;
}
}
class Passport {
private String passportNumber;
private Person owner; // Optional back-reference
public Passport(String passportNumber) {
this.passportNumber = passportNumber;
}
public String getPassportNumber() {
return passportNumber;
}
public void setOwner(Person owner) {
this.owner = owner;
}
public Person getOwner() {
return owner;
}
}
public class Main {
public static void main(String[] args) {
Person john = new Person("John Doe");
Passport johnsPassport = new Passport("ABC123XYZ");
john.assignPassport(johnsPassport);
johnsPassport.setOwner(john);
System.out.println(john.getName() + " has passport number: " + john.getPassport().getPassportNumber());
System.out.println("Passport " + johnsPassport.getPassportNumber() + " belongs to: " + johnsPassport.getOwner().getName());
}
}
Here, a Person can have a Passport, and a Passport can have an owner (Person). They are associated, but the Passport can exist even if the Person doesn't (initially), and vice-versa. Their lifecycles are generally independent.
3. Aggregation:
Concept: Aggregation is a special form of association that represents a "has-a" relationship where one object "owns" or contains other objects, but the contained objects can exist independently even if the owning object is destroyed. It implies a "whole-part" relationship, but the part can exist without the whole. It's often described as a "weak" form of association.
Key Characteristics:
Implementation in Java:
Example:
class Department {
private String name;
private java.util.List<Student> students; // Aggregation: Department has students
public Department(String name) {
this.name = name;
this.students = new java.util.ArrayList<>();
}
public void addStudent(Student student) {
this.students.add(student);
}
public java.util.List<Student> getStudents() {
return students;
}
public String getName() {
return name;
}
}
class Student {
private String studentId;
private String name;
public Student(String studentId, String name) {
this.studentId = studentId;
this.name = name;
}
public String getStudentId() {
return studentId;
}
public String getName() {
return name;
}
}
public class Main {
public static void main(String[] args) {
Department scienceDept = new Department("Science");
Student alice = new Student("S101", "Alice");
Student bob = new Student("S102", "Bob");
scienceDept.addStudent(alice); // Alice is added to the Science Department
scienceDept.addStudent(bob); // Bob is added to the Science Department
System.out.println("Students in " + scienceDept.getName() + " department:");
for (Student student : scienceDept.getStudents()) {
System.out.println("- " + student.getName() + " (" + student.getStudentId() + ")");
}
// Even if the scienceDept object is destroyed, Alice and Bob (Student objects) will still exist.
scienceDept = null;
System.out.println("Alice still exists: " + alice.getName());
}
}
In this example, a Department "has-a" list of Student objects. However, if the scienceDept object is destroyed (set to null), the Student objects (Alice and Bob) still exist independently. This demonstrates the weak relationship characteristic of aggregation.
Key Differences Summarized:
* Object-Oriented Paradigm means:
Thinking and organizing your program around "objects" instead of actions or logic.
In object-oriented programming (OOP):
You model your code as objects.
Each object bundles together data (attributes) and behaviors (methods).
Objects represent real-world things or concepts — like a Car, Person, BankAccount, etc.
* Main ideas behind OOP:
| Concept | Meaning |
|---|---|
| Class | A blueprint for creating objects (e.g., Dog, User). |
| Object | An actual instance of a class (e.g., a real dog named "Buddy"). |
| Encapsulation | Hiding data inside the object; only exposing necessary parts. |
| Inheritance | One class can inherit features (methods/attributes) from another. |
| Polymorphism | Same method name can work differently depending on the object. |
| Abstraction | Focus on essential features, hide complex details. |
* Quick example (Python):
class Dog:
def __init__(self, name):
self.name = name
def bark(self):
print(f"{self.name} says woof!")
# Creating objects
dog1 = Dog("Buddy")
dog2 = Dog("Max")
dog1.bark() # Buddy says woof!
dog2.bark() # Max says woof!
Here:
Dog is the class (template).
dog1 and dog2 are objects (instances).
bark() is a method (behavior).
Why use Object-Oriented Programming?
Code is organized and modular.
Easier to maintain and reuse.
Models real-world systems naturally.
A module is just a single Python file (.py) that can contain functions, classes, or variables.
It helps you organize your code better (instead of putting everything into one huge file).
* Example: Suppose you have a file math_utils.py:
# math_utils.py
def add(a, b):
return a + b
def subtract(a, b):
return a - b
You can then import it into another file:
import math_utils
print(math_utils.add(5, 3)) # Output: 8
* Package in Python:
A package is a collection of modules organized in folders.
A package must have an __init__.py file inside the folder (even if it's empty) — it tells Python, "Hey, this folder is a package!"
* Folder structure for a package:
mypackage/
__init__.py
math_utils.py
string_utils.py
Now you can use it like:
from mypackage import math_utils
print(math_utils.add(10, 5)) # Output: 15
* Quick Summary:
| Term | Meaning |
|---|---|
| Module | A single .py file containing code (functions, classes, etc.) |
| Package | A folder containing multiple modules and an __init__.py file |
* Real-world example:
When you do:
import numpy
You're importing the numpy package, which internally has tons of modules like numpy.linalg, numpy.random, etc.