Skip to content

CS 32 (Fall '16)

Daniel Norman edited this page Jun 5, 2017 · 1 revision

Find Single Number

Contributed by Gopi Suresh.

Given an vector of integers, every element appears twice except for one. Find that single one. Write a function singleNumbers(const vector<int> &vec) that solves this problem in O(n) time complexity.

Example

int main() {
    int nums[] = {1, 3, 2, 1, 2};
    vector<int> n(nums, nums + sizeof(nums) / sizeof(int));
    cout << singleNumber(n)<< endl;   
}

The above code prints out 3.

Solution

For a challenge, think of a way to solve this without using extra memory.

#include <unordered_set>
#include <vector>
#include <iostream>

using namespace std;

int singleNumber(const vector<int> &vec) {
    unordered_set<int> s;
    for (int i = 0; i < vec.size(); i++) {
        if (s.find(vec[i]) != s.end()) {
            s.erase(vec[i]);
        } else {
            s.insert(vec[i]);
        }
    }
    return *s.begin();
}

int main() {
    int nums[] = {1, 3, 2, 1, 2};
    vector<int> n(nums, nums + sizeof(nums) / sizeof(int));
    cout << singleNumber(n);   
}

Recursive binary search on an array

Contributed by Robert Zalog

Implement the function provided by the following function header:

int findNum(int *nums, int n, int num);,

which returns the index of a given number num in a sorted (in ascending order) array nums of length n. Your function must not use a for loop and must utilize a recursive function call. In addition, your algorithm must run in O(log n) time complexity. You can assume that the specified value will always be found in the array (e.g., function caller will not ask you to look for 3 in an array that does not contain a 3).

Hint:

You might want to use a helper function that takes a start and an end parameter instead of just n.

Example

Example function call:

int nums[6] = {1, 2, 4, 8, 10, 18};
findNum(nums, 0, 8); // returns 3

Solution

int findNumHelper(int *, int, int, int);

int findNum(int *nums, int n, int num)
{
	return findNumHelper(nums, 0, n, num);
}

int findNumHelper(int *nums, int start, int end, int num)
{
	int test = start + (end - start) / 2;
	if (nums[test] == num) {
		return test;
	}
	if (nums[test] > num) {
		return findNumHelper(nums, start, test, num);
	}
	if (nums[test] < num) {
		return findNumHelper(nums, test+1, end, num);
	}
}

Counting Leaves

Contributed by Shaan Mathur.

Assume you have a struct defined as below:

struct Tree {
    int data;
    std::vector<Tree*> children;
};

Write a function int countLeaves(Tree* head) that counts the number of leaves in a tree. HINT: Recursion and Trees tend to go very well together.

Example

	      Head
    N1			 N2
N3	N4	N5	   N6	N7

This tree has FIVE leaves.

	[nullptr]

This "tree" has no leaves.

Solution

#include <vector>

struct Tree {
    int data;
    std::vector<Tree*> children;
};

int countLeaves(Tree* head) {
    /* BASE CASES */

    // head is an empty tree, in case there are no leaves. Thus return 0.
    if (head == nullptr)
        return 0;
    // The node has no children, which is by definition a leaf. Thus return 1.
    if (head->children.size() == 0)
        return 1;

    /* RECURSION */

    // The node has children, so let's count them and return the total count.
    int count = 0;
    for (int i = 0; i < head->children.size(); i++) {
        count += countLeaves(head->children[i]);
    }

    return count;
}

generateParenthesis

Contributed by Gabriel Zhou.

Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.

Example

For example, given n = 3, a solution set is: [ "((()))", "(()())", "(())()", "()(())", "()()()" ]

Solution

vector<string> generateParenthesis(int n) {
    vector<string> res;
    addingpar(res, "", n, 0);
    return res;
}
void addingpar(const vector<string>& v, string str, int n, int m) {
    if (n == 0 && m == 0) {
        v.push_back(str);
        return;
    }
    if (m > 0) { addingpar(v, str+")", n, m-1); }
    if (n > 0) { addingpar(v, str+"(", n-1, m+1); }
}

nodeCount

Contributed by Katie Luangkote.

Write nodeCount, a recursive function that counts the number of nodes in a tree rooted at node. This is a general tree, where a node can have a variable number of children.

#include <iostream>
#include <vector>
using namespace std;

struct Node {
  int val;
  vector<Node *> children;
};

int nodeCount(Node *node) {
  int count = 1;
  for (int i = 0; i < node->children.size(); i++)
    count += nodeCount(node->children[i]);
  return count;
}

Recursively Reverse Words

Contributed by Rahul Salvi.

For this question, create a function 'printReversed' that takes a single input std::string and prints it out with the words inside reversed. A word is a sequence of characters followed by a space or newline. The input string will be terminated by a newline character. 'printReversed' should not return anything. 'printReversed' may output an extra trailing space. You may create a single helper function that takes an optional int argument. You may use a loop inside each function call to find a word. There will never be consecutive space characters.

Example

"this is a string\n" --> "string a is this " (with or without the trailing space)

"abcd\n" --> "abcd " (with or without the trailing space)

Solution

Two solutions are provided. They are both very similar except in the way that they call themselves to continue the recursion. To find a word, they iterate by characters until a space is found, appending to a temporary string. At this point, they print and return if a newline is found. Otherwise, the function is called again to find another word. Finally, the words are printed out in reverse similar to a post-order tree traversal. These solutions do print out a trailing space.

The first solution uses a helper function that tracks the index to begin looking for a word and passes it to the next call.

void printReversedHelper(std::string str, int index) {
    std::string s = "";
    int i = index;
    while (str[i] != ' ') {
        if (str[i] == '\n') {
            std::cout << s << " ";
            return;
        }
        s += str[i];
        i++;
    }
    printReversedHelper(str, i+1);
    std::cout << s << " ";
}

void printReversed(std::string str) {
    printReversedHelper(str, 0);
}

The second solution opts to remove words from the string as it finds them, then passes the shortened string to the next call.

void printReversed(std::string str) {
    std::string s = "";
    int i = 0;
    while (str[i] != ' ') {
        if (str[i] == '\n') {
            std::cout << s << " ";
            return;
        }
        s += str[i];
        i++;
    }
    printReversed(str.substr(i+1, str.length()-i));
    std::cout << s << " ";
}

Iterating through Lists

Contributed by Annika Tsai.

Given a const list of strings that represent names, write a function that will iterate through the list and print out all names that contain the letter a.

Example

given a const list of names: const list<string> names = {"George", "Ryan", "Elise", "Tom", "Hank"}, the output of the function should contain "Ryan" and "Hank". #### Solution Remember that if you pass a container as a const reference parameter, you have to use a const_iterator as opposed to a regular iterator.

void print_names(const list &names) {
   list::const_iterator it;
   for (it = names.begin(); it!= names.end(); it++) {
       string name = *it;
       for (int i = 0; i < name.length(); i++) {
           if (name[i] == 'a') cout << *it << endl;
       }
   }
}

Multiplying Two Integers Using EXCITING RECURSION

Contributed by Frank Fu.

Write a function called multiply that takes two intergers, x and y, as its arguments and returns the resulting integer product. You MUST use recursion to implement your multiply function, and you are not allowed to use any loops or the multiplication/division operators * and / in your code. Also, be sure to write a main function that prompts the user to enter the two numbers x and y before calling the multiply function in the main function to produce the product. You can assume that the user will not enter anything other than integers as inputs, but be sure to account for special cases such as when x or y is 0 or when either of them is negative.

Example

Example 1: Please enter the number x: -2 Please enter the number y: -2 The product of x and y is: 4

Example 2: Please enter the number x: 0 Please enter the number y: -1 The product of x and y is: 0

Example 3: Please enter the number x: -2 Please enter the number y: 5 The product of x and y is: -10

Example 4: Please enter the number x: 9 Please enter the number y: 4 The product of x and y is: 36

Solution

#include <iostream> 

using namespace std;

int multiply(int x, int y) {
    // 0  multiplied with anything should return 0
    if (x == 0 || y == 0)
        return 0;

    // Add x with itself with a y number of times
    // Recursively calling multiply(x, y-1)
    if (y > 0)
        return (x + multiply(x, y - 1));

    // If y is negative, we want to return the negative of the result
    if (y < 0)
        return -multiply(x, -y);
}

int main() {
  int x, y, z;
  cout << "Please enter the number x: ";
  cin >> x;
  cout << "Please enter the number y: ";
  cin >> y;
  z = multiply(x, y);
  cout << "The product of x and y is: " << z << endl;
  return 0;
}

Breadth-First Traversal of Binary Tree

Contributed by Jason Yee.

Suppose the following structure represented a node in a binary tree: struct Node { int value; Node* left; Node* right; }; Write a function, printTree, that accepts a pointer to a Node and prints the contents of the tree in a breadth-first order, with each value on its own line, assuming that the passed Node is the root of the tree.

#include <iostream>

struct Node {
    int value;
    Node* left;
    Node* right;
};

void printTree(Node* root) {
    /*The cleanest way to write this code is to use a recursive algorithm; this is
    the methodology demonstrated in this example of a solution.
    If you'd like to practice a non-recursive approach, you will need to use make
    good use of an arbitrary data structure to hold Node* values; you may wish
    to dynamically allocate and reallocate memory for an array, or use one of the
    C++ STL's various containers.*/
    
    if (root != nullptr) { /*Shouldn't do anything if there is no Node to handle*/
        /*The basis of the breadth-first traversal is to first handle the data
        held by the current node, then perform the same process for each Node's
        children.*/
        
        /*First, print the current node's value:*/
        std::cout << root->value << endl;
        
        /*Now repeat the process described above for each of the children.
        Each child is the root of a subtree that can be processed through
        a breadth-first transversal.
        This is why a recursive algorithm is suitable.
        Don't worry about passing nullptr to printTree in the case where a
        child does not exist; the check we did at the start of this function
        fixes that.*/
        printTree(root->left);
        printTree(root->right);
    }
}

Finding the duplicate value in an array

Contributed by Ryan Lo.

Given a random array of strings with only 1 duplicate, write a function called "getDup()" to return the duplicate string in O(n) time. If no duplicates, return the string "-1". The function takes the string array and the size of the array as inputs

Example:

If given an array:

    string s[] = {"go", "bruins", "defeat", "the", "USC", "trojans", "we", "beat", "USC"};

     then getDup(s, 9) should return "USC" as the duplicate string 
#include <iostream>
using namespace std;
#include <string>
#include <cassert>
#include <unordered_map>

string getDup(string s[], int n) {
    unordered_map<string, bool> map;
    for (int i = 0; i < n; i ++) {
        if (map[s[i]] == true) return s[i];
        map[s[i]] = true;
    }
    return "-1";
}

int main() {
    /*Given a random array of strings with only 1 duplicate, write a function to return the duplicate string in O(n) time. If no duplicates, return the string "-1". The function takes the string array and the size of the array as inputs
    */
    string s[] = {"go", "bruins", "defeat", "the", "USC", "trojans", "we", "beat", "USC"};
    string dup = getDup(s, 9);
    assert(dup == "USC");
    cout << "All cases worked" << endl;
}

Car Dealership

Contributed by John Stucky.

Suppose you have a car dealership that has a collection of cars. Each car has a make, model, unique car ID number, and price. Describe one or more data structures that can do the following:

(a) Given a car manufacturer/make (e.g., Toyota), generate a collection of unique models made by that manufacturer present at the dealership.

(b) Given a car's unique ID number, find the next most expensive car (so the dealer can upsell a customer).

Then use these data structures to implement a CarDealership class that is constructed from a collection of cars and can perform the operations listed above. The code for Car and a prototype for CarDealership have been provided.

struct Car{

    int id;
    string make;
    string model;
    double price;
    explicit Car(int i = -1, string m = "", string n = "", double p = -1.0) {
        id = i;
        make = m;
        model = n;
        price = p;
    }
    bool operator<(const Car& rhs) const;
};

bool Car::operator<(const Car& rhs) const {
  return price < rhs.price;
}

class CarDealership{
 public:
    explicit CarDealership(const vector<Car>& cars);  // to be implemented
    vector<string> car_models(string manufacturer);  // to be implemented
    Car upsell(int id);  // to be implemented
 private:
    // to be implemented
};

Example

A small CarDealership has 7 cars:

ID Make Model Price
1 Toyota Camry 20000
2 Toyota Prius 28000
3 Toyota 4Runner 36000
4 Ford Focus 18000
5 Ford F150 27000
6 Toyota Camry 19000
7 Ford F150 26150

A call to car_models("Toyota") should return a vector of size 3 with strings "Camry", "Prius", "4Runner" in any order. A call to upsell(5) should return a car with id, make, model, and price of 2, Toyota, Prius, 28000, respectively.

Solution

One sensible way to efficiently compute the list of models given a manufacturer is to use a hash table, or an unordered map, from each make to its associated models, where the models are an unordered set. Explicitly, this is an unordered_map<string, unordered_set<string>>.

To quickly find a car given its ID, one can use an unordered map from IDs to Cars: unordered_map<int, Car>. Then once one has a Car object, one can find the next most expensive car by using an ordered set, sorted by price: set<Car>.

#include <vector>
#include <string>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <iostream>
using namespace std;

struct Car{
    int id;
    string make;
    string model;
    double price;
    explicit Car(int i = -1, string m = "", string n = "", double p = -1.0) {
        id = i;
        make = m;
        model = n;
        price = p;
    }
    bool operator<(const Car& rhs) const;
};

bool Car::operator<(const Car& rhs) const {
  return price < rhs.price;
}

class CarDealership{
 public:
    explicit CarDealership(const vector<Car>& cars);
    vector<string> car_models(string manufacturer);
    Car upsell(int id);
 private:
    unordered_map<string, unordered_set<string>> makeToModels;
    unordered_map<int, Car> idToCar;
    set<Car> carBST;
};

CarDealership::CarDealership(const vector<Car>& cars) {
    for (int i = 0; i < cars.size(); i++) {
        Car currentCar = cars[i];
        unordered_map<string, unordered_set<string>>::iterator it;
        it = makeToModels.find(currentCar.make);
        if (it == makeToModels.end()) {
            unordered_set<string> models;
            models.insert(currentCar.model);
            makeToModels.insert(pair<string, unordered_set<string>>(currentCar.make, models));
        } else {
            (it->second).insert(currentCar.model);
        }
        idToCar[currentCar.id] = currentCar;
        carBST.insert(currentCar);
    }
}

vector<string> CarDealership::car_models(string manufacturer) {
    unordered_map<string, unordered_set<string>>::iterator it = makeToModels.find(manufacturer);
    vector<string> matches;
    if (it == makeToModels.end()) {
        return matches;
    } else {
        unordered_set<string>& models = it->second;
        for (unordered_set<string>::iterator it2 = models.begin(); it2 != models.end(); ++it2) {
            matches.push_back(*it2);
        }
    }
    return matches;
}

Car CarDealership::upsell(int id) {
    unordered_map<int, Car>::iterator it = idToCar.find(id);
    if (it == idToCar.end()) {
        Car c;
        return c;
    }
    set<Car>::iterator it2 = carBST.find(it->second);
    ++it2;  // increment to the next car by price
    if (it2 == carBST.end()) {
        Car c;
        return c;
    }
    return (*it2);
}

int main() {
    Car c1(1, "Toyota", "Camry", 20000);
    Car c2(2, "Toyota", "Prius", 28000);
    Car c3(3, "Toyota", "4Runner", 36000);
    Car c4(4, "Ford", "Focus", 18000);
    Car c5(5, "Ford", "F150", 27000);
    Car c6(6, "Toyota", "Camry", 19000);
    Car c7(7, "Ford", "F150", 29000);
    vector<Car> cars;
    cars.push_back(c1);
    cars.push_back(c2);
    cars.push_back(c3);
    cars.push_back(c4);
    cars.push_back(c5);
    cars.push_back(c6);
    cars.push_back(c7);
    CarDealership dealer(cars);
    vector<string> tmodels = dealer.car_models("Toyota");
    for (int i = 0; i < tmodels.size(); i++) {
        cout << tmodels[i] << " ";
    }
    cout << endl;
    Car up = dealer.upsell(c6.id);
    cout << up.make << " " << up.model << " " << up.price << endl;
}

Maximum Height of a Binary Tree

Contributed by Stephanie Lam.

Given the following struct for a node of a binary tree, write the getHeight function, which determines the maximum height of the tree. The maximum height is defined as the maximum number of nodes in the longest path from the root node to a leaf node. The parameter passed into the getHeight function is the node of the tree.

struct Node {
    int val;
    Node* left;
    Node* right;
}

int getHeight(Node* n) {
    // complete function 
}

Solution

The solution can be found using recursion. We get the height of the left subtree and the height of the right subtree, and then take the maximum value of the two, adding 1 for the root node.

int getHeight(Node* n) { 
    if (n == nullptr) {
        return 0;
    } else {
        int left_height = getHeight(n->left);
        int right_height = getHeight(n->right);
        // return the max height between the left and right subtrees 
        if (left_height < right_height) 
            return right_height + 1;
        else
            return left_height + 1;
    }
}

Given a linked list, determine if it has a cycle in it

Contributed by Yiyin Jin.

Given a linked list, determine if it has a cycle in it.

Solution

We go through each node one by one and record each node's reference (or memory address) in a hash table. If the current node is null, we have reached the end of the list and it must not be cyclic. If current node’s reference is in the hash table, then return true.

public boolean hasCycle(ListNode head) {
  Set<ListNode> nodesSeen = new HashSet<>();
  while (head != null) {
    if (nodesSeen.contains(head)) {
      return true;
    } else {
      nodesSeen.add(head);
    }
    head = head.next;
  }
  return false;
}

Index of Non Repeated Character

Contributed by Jason Wong.

Write a function to determine the index of the first non-repeated character in a string. If no non-repeated characters exist, return -1. The string we pass in will consist of only characters a-z; that is, only lower cased letters. Strive for efficiency. After you are done, analyze the time and space complexity of your function. Can you do better?

Function skeleton below:

int firstUniqueCharacter(string s) {
}

Examples

Input: abbccdd Output: 0, because a is non-repeated, and is at index 0

Input: aabbcdefg Output: 4, because c is the first non-repeated character in the string

Input: aabbccddeee Output: -1, because there are no non-repeated characters

Solution

#include <string>
using namespace std;

/*
Analysis:
The time complexity of my function is O(s), where s is the length of the string
We loop through 26 characters, then loop through our string twice. Look up in 
my int array is O(1). We have O(26 + s + s), which is O(s)
My function uses O(1) space; I only use an int array, of size 26.
*/
int firstUniqueCharacter(string s) {
    // We do not need a BST or Hash table. We know that there are 26 lower cased letters
    int map[26];
    for (int i = 0 ; i < 26; i ++) {
        map[i] = 0;
    }

    // Each entry int the array indicates the count of eah character    
    for (int i = 0 ; i < s.size() ; i++) {
        int index = s[i] - 'a';
        map[index]++;
    }
    
    for (int i =  0 ; i < s.size() ; i++) {
        int index = s[i] - 'a';
        // If we only saw the character once, this is the first non-repeated character
        if (map[index] == 1) {
            return i;
        }
    }
    // If reached here, we havent found a non-repeated character
    return -1;
}

Length of Largest Increasing Subsequence

Contributed by Jung Hyun Park.

Given a vector set of numbers, write a program that would find the length of the longest increasing subsequence of the vector.

Example

vector<int> v{ 1, 4, 2, 9, 12, 7, 6 };
cout << "Length is: " << coolFunc(v);
Try it out friends!
#include <iostream>
#include <vector>
using namespace std;

int bSearch(const vector<int> &v, int l, int r, int key) {
    while (r-l > 1) {
    int m = l + (r-l)/2;
    if (v[m] >= key)
        r = m;
    else
        l = m;
    }
    return r;
}

int coolFunc(const vector<int> &v) {
    if (v.size() == 0)
        return 0;

    vector<int> temp(v.size(), 0);
    int length = 1;  // length of longest subsequence
    temp[0] = v[0];
    for (int i = 1; i < v.size(); i++) {
        if (v[i] < temp[0])
            temp[0] = v[i];  // change smallest value
        else if (v[i] > temp[length-1])
            temp[length++] = v[i];  // add term to subsequence
        else
            temp[bSearch(temp, -1, length-1, v[i])] = v[i];
    }
    return length;
}

Are two strings anagrams?

Contributed by Justin Hong.

Write a function to determine whether two strings are anagrams. You may use the std::sort function after including .

Solution

Two strings are anagrams if they have the same number of same letters. Therefore strings that are anagrams must be identical after they are both sorted.

#include <string>
#include <vector>
using namespace std;
bool isAnagram(string first, string second) {
    if (first.size() != second.size()) return false;
    sort(first.begin(), first.end());
    sort(second.begin(), second.end());
    if (first == second) return true;
    return false;
}

Queue of Two Stacks

Contributed by William Shao.

Implement a FIFO (first in first out) queue class. The only member variables you can use are two std::stacks. Implement the class using the following skeleton:

#include <stack>
class StackQueue{
    private:
        std::stack<int> stackOne;
        std::stack<int> stackTwo;
    public:
        void push(int x) { //Push an int into the queue

        }
        
        void pop(){ //Remove the oldest int in the queue
        
        }

        int front() { //Return the oldest value queue (Don't remove it)

        }
}

Solution

Imagine putting the stacks head to tail. We push to the top of one stack and when we want to pop, we "pour" the contents of the first stack into the second, so now the oldest values are on top and newest on bottom.

#include <stack>
class StackQueue {
 private:
        std::stack<int> stackOne;
        std::stack<int> stackTwo;
        
 public:
        void push(int x) {  // Push an int into the queue
            stackOne.push(x);
        }

        void pop() {  // Remove the oldest int in the queue
            if (stackOne.empty() && stackTwo.empty()) {
                return;
            }
            
            if (stackTwo.empty()) {
                while (!stackOne.empty()) {
                    stackTwo.push(stackOne.top());
                    stackOne.pop();
                }
            }
            stackTwo.pop();
        }

        int front() {  // Return the oldest value queue (Don't remove it)
            if (stackTwo.empty()) {
                while (!stackOne.empty()) {
                    stackTwo.push(stackOne.top());
                    stackOne.pop();
                }
            }
            return stackTwo.top();
        }
}

Remove Duplicates

Contributed by Jennifer Tan.

Write a function that takes a sorted linked list of ints and remove all nodes with duplicates values.

Solution

struct node {
    int value;
    node *next;
};

void removeDuplicates(node* root) {
    node* curr = root;
    while (curr != nullptr && curr->next != nullptr) {
        if (curr->value == curr->next->value) {
            curr->next = curr->next->next;
        } else {
            curr = curr->next;
        }
    }
}

Palindromes with Queues and Stacks

Contributed by Chaoran Lin.

Given a string representing a word, determine if it is a palindrome using a queue and a stack.

Examples

Input: racecar Output: True

Input: avid diva Output: True

Input: butterfly Output: False

Solution

A stack as a LIFO (last-in-first-out) data structure while a queue is FIFO (first-in-first-out). Using this knowledge, we can see that if a string is a palindrome, after pushing all of its characters to a stack and a queue, the stack would be identical to the queue. Therefore we can simply iterate through the stack and queue and compare their characters.

#include <iostream>
#include <queue>
#include <stack>

using namespace std;

bool isPalindrome(string s) {
    stack<char> st;
    queue<char> q;
    for (int i = 0; i < s.length(); i++) {
        st.push(s[i]);
        q.push(s[i]);
    }

    bool isPalindrome = true;

    for (int i = 0; i < s.length() / 2; i++) {
        if (st.top() != q.front()) {
            isPalindrome = false;
            break;
        }
        st.pop();
        q.pop();
    }
    return isPalindrome;
}

Intersection of Vectors

Contributed by Neda Vesselinova.

Given two integer vectors, compute the intersection of the vectors using the find function. The intersection is a vector consisting of all elements that appear in both vectors. Note that the input vectors may have repeated integers, but the intersection should not.

Example

vector<int> x;
x.push_back(1);
x.push_back(2);
x.push_back(3);
x.push_back(2);
x.push_back(7);

vector<int> y;
y.push_back(7);
y.push_back(3);
y.push_back(6);
y.push_back(2);
y.push_back(9);

vector<int> z = intersection(x, y)

Vector z should consist of 2, 3, and 7 (in any order).

Solution

For every element of vec1, check whether it is also in vec2 and has not already been added to the intersect vector. If so, add it to the vector. You only need to iterate through every element of one of the vectors because any elements that belong in the intersection will appear in either vector.

vector<int> intersection(vector<int> vec1, vector<int> vec2) {
    vector<int> intersect_vector;

    for (int i = 0; i < vec1.size(); i++) {
        if ((find(vec2.begin(), vec2.end(), vec1[i]) != vec2.end()) &&
            (find(intersect_vector.begin(), intersect_vector.end(), 
                  vec1[i]) == intersect_vector.end()))
           intersect_vector.push_back(vec1[i]);
    }
    return intersect_vector;
}

Two Sum Class

Contributed by Omar Ozgur.

Create a class TwoSum that includes a data structure of your choice. Create a function insert that inserts an integer into the data structure, a function remove that removes a specified integer from the data structure, and a function findSum that returns true if there is a pair of integers that add to the given target value, and false otherwise. You are free to use any standard libraries that were covered in class. Note: There are many correct answers. Think about using data structures that would lead to increased efficiency.

Example

TwoSum ts;
ts.findSum(0) => false
ts.insert(0);
ts.findSum(0) => true
ts.insert(1);
ts.insert(2);
ts.insert(3);
ts.findSum(5) => true;
ts.remove(3);
ts.findSum(3) => true;
ts.findSum(5) => false;

Solution

In the solution below, an unordered_set is used to store integers, which allows for efficient lookups for the remove and findSum methods. The method used allows for the target sum to be found in a single traversal of the elements. However, it is possible to make findSum run in constant time if more time and space is used in the insert and remove methods.

#include <unordered_set>
#include <cassert>
    using namespace std;

class TwoSum {
    public:
        void insert(int x);
        void remove(int x);
        bool findSum(int target);
 
    private:
        unordered_set<int> seen;
};

void TwoSum::insert(int x) {
    seen.insert(x);
}

void TwoSum::remove(int x) {
    seen.erase(x);
}

bool TwoSum::findSum(int target) {
    if (seen.find(target) != seen.end())
        return true;
    for (unordered_set<int>::iterator it = seen.begin(); it != seen.end(); it++) {
    	// target = (target - *it) + *it
    	// Since we iterate with it, *it is known
    	// target is also known, so ll we need is (target - *it)
        if (seen.find(target - *it) != seen.end()) {
            return true;
        }
    }
    return false;
}

int main() {
    TwoSum ts;
    assert(ts.findSum(0) == false);
    ts.insert(0);
    assert(ts.findSum(0) == true);
    ts.insert(1);
    ts.insert(2);
    ts.insert(3);
    assert(ts.findSum(5) == true);
    ts.remove(3);
    assert(ts.findSum(3) == true);
    assert(ts.findSum(5) == false);
}

Loopless Array Sum

Contributed by Matthew Wong.

Given an array of integers, write a function to return the sum of all the elements in the array. Do not use a loop of any kind! You must use recursion! Use this as the head of your function: int arraySum(int a[], int n)

Solution

int arraySum(int a[], int n) {
    // Base case: no more elements to add
    if (n == 0)
        return 0;
        
    // Recursive case: add to current with array of one less element
    int sum = a[0] + arraySum(a+1, n-1);
    
    return sum;
}

Counting Array Duplicates (Part 2)

Contributed by Jason Xu.

Given an unsorted 2D array of integers, write a function that returns the number of integers in the array that appear more than once. The width and height of the array will also be given as parameters.

Example

Input: nums = { {3, 1, 2, 2}, {40, 1, 1, 1}, {5000, 40, 8, 3} } height = 3 width = 4

Output: 4

Solution

This is only one possible solution that runs in O(n). Some of the #includes might not be needed.

#include <stdio.h>
#include <iostream>
#include <string>
#include <unordered_map>
    using namespace std;

int countDups(int ** arr, int height, int width) {
    if (width < 1 || height < 1)
        return 0;
  
    // An unordered map allows constant lookup (if small amount of collisions)
    unordered_map<int, int> vals;
    unordered_map<int, int>::const_iterator checker;
  
    int curr = 0;
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
        curr = arr[i][j];
      
        // Check if our unordered_map already has the value
        checker = vals.find(curr);
        // If not, add it as a new value
        if (checker == vals.end())
            vals.insert({curr, 0});
        // Otherwise increment occurences of that value
        else
            vals[curr]++;
        }
  }

  // Count all unique elements with more than one occurence
  int count = 0;
  for (checker = vals.begin(); checker != vals.end(); checker++)
        if (checker->second > 0)
        count++;
  return count;
}

Code Tracing Through Classes and Structs

Contributed by Yi Peng.

Using the already defined NoisyClass, what will the following code print out?

#include <iostream>
using namespace std;

class NoisyClass {
  private:
    string s;

  public:
    NoisyClass() {
        cout << "[C] Default constructor" << endl;
    }

    explicit NoisyClass(string stuff) {
        s = stuff;
        cout << "[P] Parameterized constructor" << endl;
    }

    NoisyClass(const NoisyClass& other) {
        s = other.s;
        cout << "[~] Copy constructor" << endl;
    }

    ~NoisyClass() {
        cout << "[D] Destructor" << endl;
    }

    NoisyClass& operator= (const NoisyClass& other) {
        s = other.s;
        cout << "[=] Assignment" << endl;
        return *this;
    }
};

struct SoMeta {
    NoisyClass n[2];
    NoisyClass* ptr[2];
};

int main() {
    SoMeta s;
    SoMeta* ptr;
    SoMeta* dynamicYo = new SoMeta();
    delete dynamicYo;
}

Solution

[C] Default Constructor [C] Default Constructor [C] Default Constructor [C] Default Constructor [D] Destructor [D] Destructor [D] Destructor [D] Destructor


Invert Binary Tree

Contributed by Bowei Wang.

Given the root of a binary tree, write a function invertTree() to invert all the child nodes. The structure for each node is given below: Struct Node { int val; Node* left; Node* right; }

Solution

void invertTree(Node* root) {
    if (root == NULL)
        return;
    Node* temp = root->right;
    root->right = root->left;
    root->left = temp;
    invertTree(root->right);
    invertTree(root->left);
}

Linked List Implementation

Contributed by Jeffrey Jiang.

Consider the following code segment. We want to use the defined classes to implement an ordered linked list (ascending order).

class Node {
  public: 
    virtual int size();
    virtual Node* add(int val);
    virtual bool contains(int val);
};

class Empty : Node {
  public: 
    virtual int size() {
        return 0;
    }
    virtual Node* add(int val) {
        return new Node*(val, this);
    }
    virtual bool contains(int val) {
        return false;
    }
};

class Element : Node {
  public: 
    Element(int e, Node* n) {
        next = n;
        elem = e;
    }

    // Implement size(), contains(), and add()
    virtual int size();
    virtual Node* add(int val);
    virtual bool contains(int val);
    
  private: 
    Node* next; 
    int elem;
};

Using polymorphism, implement the size(), add(), and contains() in the Element class so that for any initialized Node* list, list->size() will return the size of the list. Assume that there are only unique values in this linked list, so if we are trying to add a value that is already in the list, just leave the list unchanged. HINT: We have provided the definition for Empty. See the definition of Empty and figure out what Empty as a Node means and use the things returned as hints to implementing the Element functions.

You are not allowed to use NULL or nullptr in your implementation and you cannot define any new member variables or helper functions.

Solution

class Element : Node {
  public: 
    Element(int e, Node* n) {
        next = n;
        elem = e;
    }

    virtual int size() {
        return 1 + next->size();
    }

    virtual Node* add(int val) {
        if (val == elem)
            return this;
        else if (val < elem) // we just found the location to insert. 
            return new Element(val, this);
        else {
            next = next->add(val); 
            return this;
        }
    }

    virtual bool contains(int val) {
        if (val == elem)
            return true;
        if (val < elem) // we are past that value. 
            return false; 
        return next->contains(val);
    }
    
  private: 
    Node* next; 
    int elem;
};

The main points to consider in this problem are using polymorphism and the recursive nature of linked lists to implement each problem. While the solution is very simplistic, it is actually quite a difficult problem for those who have not seen this before.

Based on the data structures that we are given, Empty is defined to be a class that represents the "end" of the list, acting as the NULL at the end of the list. However, because of polymorphism, it can provide the end conditions of each of the "recursive" functions. Thus, every Element will eventually point to the Empty node.

Size is the easiest to implement. Because we do not have anything saved for the size of the list, we can only compute it by traversing the entire list and counting the number of nodes are in the list. This can be done by calling the size of the list defined by the next node and then adding one to it.

Next, contains is the next easiest to implement. Clearly, if the node we are looking at contains the element that we are looking for, we return true. If the value we are looking for is less than the element of the node we are looking at, that means that, because of the ordered property of the list, we have passed the value without finding it, and so we return false. Otherwise, we ask the next node to see if it has found the value, and simply return that value.

Finally, based on these two, we can take it to the next level in add. It is similar to contains, in that we have to find the location of where the value has to go. After we find it, however, the trick is that we want to create a new node that points to the node we are looking at and return that node back to the previous caller. This allows us to update the pointer above to include every node that has been created.

Additionally, it may be of interest to note that in order to avoid memory leaks, a destructor must be defined for the class to remove all the children.


Is Binary Tree Balanced?

Contributed by Prathyush Katukojwala.

Write a function to check if a binary tree is balanced. A binary tree is balanced if, for any node, the left and right subtrees do not differ by more than 1 in height.

Solution

struct TreeNode {  // TreeNode struct
    int val;
    TreeNode* left;
    TreeNode* right;
};

bool isBalanced(TreeNode* node) {
    // An empty tree is balanced
    if (node == nullptr) 
        return true;
        
    // Difference in height of left and right subtrees must be within 1
    // Both subtrees must be balanced
    return abs(height(node->left) - height(node->right)) <= 1
           && isBalanced(node->left)
           && isBalanced(node->right);
}

int height(TreeNode* root) {
    // Height of an empty tree is 0
    if (root == nullptr)
        return 0;
    // Height of a tree is 1 more than the height of the longer
    // of the left and right subtrees
    return 1 + max(height(node->left), height(node->right));
}

Middle of a Linked List

Contributed by Christian Warloe.

Write a function that takes in a pointer to a node representing the head of a linked list and return a pointer to the middle of that list.

Solution

struct node{
    int val;
    node* next;
};
node* middle(node* head) {
    node* middle = head;
    if (head == nullptr)
        return head;
    node* end = head;
    while (end != nullptr) {
        if (end->next == nullptr)
            break;
        end = end->next->next;
        middle = middle->next;
    }
    return middle;
}

Remove Non-Terminal Node from Linked List

Contributed by Hongyi Zhang.

Given just the pointer to a non-terminal Node within a singly linked linked list, remove the given element from the linked list. (While preserving the integrity of the data structure of course!)

Example

1 -> 2 -> 3 -> 4
removeNode(&<second_node>)
1 -> 3 -> 4

Solution

This problem is actually pretty trivial if you think about it! Instead of removing the given element, why not acquire the value of the next element, and remove that instead? This will allow us to ensure the linked list is still properly linked!

#include <iostream>
#include <vector>
    using namespace std;

struct Node {
    explicit Node(int v) : val(v), next(nullptr) {}
    Node* next;
    int val;
};

void removeNode(Node* n) {
    // n is a non-terminal node of some linked list
    // Let's remove the next element in the node instead
    Node* to_remove = n->next;
    
    // Acquire the next element's value
    n->val = n->next->val;
    
    // Point ourselves to the subsequent element
    n->next = n->next->next;
    
    // De-allocate the removed element
    delete to_remove;
}

void printList(Node* head) {
    cout << "Printing list: ";
    while (head != nullptr) {
        cout << head->val << " ";
        head = head->next;
    }
    cout << endl;
}

int main() {
    vector<Node*> ptrs;
    Node* head = new Node(0);
    ptrs.push_back(head);
    Node* prev = head;
    
    for (int i = 1; i < 10; i++) {
        Node* n = new Node(i);
        ptrs.push_back(n);
        prev->next = n;
        prev = n;
    }
    
    printList(head);
    removeNode(ptrs[3]);
    printList(head);
    removeNode(ptrs[0]);
    printList(head);
    removeNode(ptrs[8]);
    printList(head);
}

split() Function

Contributed by Jeffrey Chan.

Implement a function split that takes in a string and returns a vector of strings such that each string within the vector is a substring of the original string that was separated by a space. You are allowed to use the C++ string and vector libraries.

Function declaration: vector<string> split(string s)

Example

string s = "Jeffrey is a genius!";
vector<string> splitString = split(s);

// Vector splitString should look like:
// ["Jeffrey", "is", "a", "genius!"]

// Each string in the vector was separated by a space in original string

Solution

vector<string> split(string s) {
    vector<string> answer;
    string temp = "";
    for (int k = 0; k < s.size(); k++) {
        if (s[k] != ' ') {
            temp += s[k];
        } else {
            answer.push_back(temp);
            temp = "";
        }
    }
    answer.push_back(temp);
    return answer;
}

Calculus + Coding: Everyone's Favorite

Contributed by Jeremiah Fan.

We can represent a term in a polynomial as an array with the first element being the coefficient and the second element being the exponent. A polynomial can be represented as an array/vector of these terms. Given such an array, write a function that "takes the derivative" of this "polynomial". Function signature: vector<int*> derive(vector<int*> polynomial);

Example

We are using vectors - this array literal syntax is just for our own understanding.

derive([[1, 2], [3, 4], [5, 6]]) => [[2, 1], [12, 3], [30, 5]]
derive([[2, 0], [4, 3], [6, 5]]) => [[12, 2], [30, 4]]

Solution

vector<int*> derive(vector<int*> polynomial) {
    int index = -1;
    for (vector<int*>::const_iterator iterator = polynomial.begin();
        iterator != polynomial.end(); iterator++) {
        // Multiply coefficient by the power
        (*iterator)[0] *= (*iterator)[1];
        // Subtract one from the power
        (*iterator)[1]--;
        
        if ((*iterator)[0] == 0) {
            index = iterator - polynomial.begin();
            delete *iterator;
        }
    }
    if (index != -1)
        polynomial.erase(polynomial.begin() + index);
    return polynomial;
}

Find a Node in a Binary Tree

Contributed by Rohan Varma.

bool exists(Node *root, Node *dest) Returns true if a node exists in a binary tree.

Solution

// Type your code here, or load an example.
#include <string> 
#include <vector>
 using namespace std;

struct Node {
  int val; 
  Node *left, *right; 
};


bool exists(Node *root, Node *dest) {
    if (!root || !dest) {
        return false; 
    }
    if (root == dest) {
        return true;
    }
    return exists(root->left, dest) || exists(root->right, dest);
}

Swap Adjacent Pairs in Linked List

Contributed by Adam Romayor.

Write a function swapPairs that is passed the head of a singly linked list and swaps adjacent nodes. Return the head of the new list. You may not change the value of the node.

Definitions for the problem:

struct ListNode {
  int val;
  ListNode *next;
  ListNode(int x) : val(x), next(NULL) {}
};


ListNode* swapPairs(ListNode* head);

Example

1->2->3->4 should return 2->1->4->3 NULL returns NULL 1->2->3->4->5 returns 2->1->4->3->5 1 returns 1

Solution

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};

ListNode* swapPairs(ListNode* head) {
    if (head == NULL) return NULL;
    if (head->next == NULL) return head;
    ListNode* curr = head;
    ListNode* nxt = head->next;
    ListNode* hd = nxt;
    ListNode *prev = NULL;

    while (curr!= NULL) {
        if (nxt != NULL) {
            if (prev != NULL)  
                prev->next = nxt;
            curr->next = nxt->next;
            nxt->next = curr;
        }
    prev = curr;
    curr = curr->next;
    if (curr != NULL)
    nxt = curr->next;
    }
    
    return hd;
}

Search of a Binary Search Tree

Contributed by Connor Borden.

Given the head of a binary search tree and an integer, write a function that returns whether the integer is within the binary search tree. Write this function without recursion. Here is a skeleton for the problem:

struct Node {
  Node* left;
  Node* right;
  int val;
};

bool search(Node* a, int dest) {
  *Enter code here*
}

Solution

struct Node {
  Node* left;
  Node* right;
  int val;
};

bool search(Node* a, int dest) {
  while (a != nullptr) {
    if (a->val == dest)
      return true;
    else if (a->val > dest)
      a = a->left;
    else
      a = a->right;
  }
  return false;
}

Balanced Parentheses Question

Contributed by Ramya Satish.

Given a string, return true if the string is "balanced" in terms of parentheses, and false if it is not. Note that multiple types of parentheses / brackets may be used, and all of these have to be balanced. The brackets must open and close in the correct order.

Example

"()" -> true
"[]()" -> true
"{" -> false
"[]]" -> false
"[()]" -> true
"[(])" -> false

Solution

#include <string> 
#include <stack>
using namespace std;

class Expression {
  public:
    bool isValidParen(string s) {
      stack<char> paren;
         
      for (int i = 0; i < s.size(); i++) {
        if (s[i] == '(' || s[i] == '[' || s[i] == '{') {
          paren.push(s[i]);
        }
        if (s[i] == ')' || s[i] == ']' || s[i] == '}') {
          if (paren.size() == 0) {
            return false;
          } else if (s[i] == ')' && paren.top() != '(') {
            return false;
          } else if (s[i] == ']' && paren.top() != '[') {
            return false;
          } else if (s[i] == '}' && paren.top() != '{') {
            return false;
          }
          paren.pop();
        }
      }
      if (paren.size() != 0) {
        return false;
      }
      return true;
    }
};

Depth of X

Contributed by Alex Wu.

Given a pointer to the root of a binary tree, with nodes declared as follows:

struct node {
  int value;
  node *left;
  node *right;
};

Write a recursive function, depth_of_x, that returns the depth of the shallowest node that holds the value x. Your function should return 1 if x is held in the rood node, and 0 if x cannot be found. Use the following header:

int depth_of_x(node * root, int x) {}

Example

For example, given the tree with nodal values:

       3
      / \
     4   5
    / \   \
   2   1   4

depth_of_x(root, 4) should return 2.

Solution

#include <algorithm>

struct node {
  int value;
  node *left;
  node *right;
};

int depth_of_x(node * root, int x) {
  if (root == nullptr)
    return 0;
  if (root->value == x)
    return 1;

  int left_depth = depth_of_x(root->left, x);
  int right_depth = depth_of_x(root->right, x);

  // If x is found in both right and left, increment depth of shallower one
  if (left_depth != 0 && right_depth != 0)
    return std::min(left_depth, right_depth) + 1;

  // If x is found in left but not right, increment depth of left
  if (left_depth != 0)
    return left_depth + 1;

  // If x is found in right but not left, increment depth of right
  if (right_depth != 0)
    return right_depth + 1;

  // x was not found in either
  return 0;
}

Remove Node from Linked List

Contributed by Matt Fabius.

Write a function that traverses a linked list and removes the first instance of a Node with a given value.

Solution

#include <iostream>
using namespace std;

class Node {
  public:
    int m_value;
    Node* m_next;
    Node* m_prev;
};

void remove(int val, Node* head) {
  if (head == nullptr) {
    return;
  } else if (head->m_value == val) {
    head->m_prev->m_next = head->m_next;
    head->m_next->m_prev = head->m_prev;
    delete head;
    return;
  }
  
  Node* p = head->m_next;
  for (; p != head; p = p->m_next) {  // for a circular linked list
    if (p == nullptr) {
      return;
    } else if (p->m_value == val) {
      p->m_prev->m_next = p->m_next;
      p->m_next->m_prev = p->m_prev;
      delete p;
      return;
    }
  }
}

First Missing Number

Contributed by Michael Li.

Given a list of unique positive integers, find the smallest missing integer not in the list, starting from 1.

Example

[] -> 1
[1, 4, 3] -> 2
[4, 2, 5, 1, 3] -> 6

Solution

You can sort the list and look for the first integer that's not in the list, starting at 1. This is an O(n * log n) algorithm. To get O(n), maintain a hash table that contains the integers in the list. Then, starting from 1, test if the integer is in the hash table and return the first one that isn't.

#include <vector>
#include <unordered_set>
#include <limits.h>
using namespace std;

unsigned firstMissing(vector<unsigned> boxNums) {
  unordered_set<unsigned> foundNums;
  for (unsigned i = 0; i < boxNums.size(); i++) {
    foundNums.insert(boxNums[i]);
  }
  for (unsigned i = 1; i < UINT_MAX; i++) {
    if (!foundNums.count(i)) {
      return i;
    }
  }
  return UINT_MAX;
}

Lowest Common Ancestor

Contributed by Aniqa Kamal.

Find the lowest common ancestor of two nodes in a binary tree.

Solution

struct Node {
  int val;
  Node* left, right;
};

Node* findLowestCommonAncestor(Node* root, Node* a, Node* b) {
  if (!root || !a || !b)
    return NULL;
  if (a->val == root->val || b->val == root->val)
    return root;
  Node* left = findLowestCommonAncestor(root->left, a, b);
  Node* right = findLowestCommon(root->right, a, b);
  
  if (left && right)
    return root;
  else if (left)
    return left;
  return right;
}

Multiple Inheritance Constructor/Destructor Order

Contributed by Aditya Padmakumar.

What is the output of the following program?

#include<iostream>
using namespace std;

class Base1 {
  public:
    Base1() { 
      cout << "Base1's constructor called" << endl;  
    }
    ~Base1() { 
      cout << "Base1's destructor called" << endl;  
    }
};

class Base2 {
  public:
    Base2() { 
      cout << "Base2's constructor called" << endl;  
    }
  ~Base2() { 
    cout << "Base2's destructor called" << endl;  
  }
};

class Derived: public Base1, public Base2 {
  public:
    Derived() {  
      cout << "Derived's constructor called" << endl;  
    }
  ~Derived() { 
    cout << "Derived's destructor called" << endl;  
  }
};

int main() {
  Derived d;
  return 0;
}

Solution

Base1's constructor called
Base2's constructor called
Derived's constructor called
Derived's destructor called
Base2's destructor called
Base1's destructor called

In cases of Multiple Inheritance, constructors of base classes are always called in derivation order from left to right and Destructors are called in reverse order.


LotsOfFours

Contributed by Brendon Daugherty.

Write the function lotsOfFours that, given a non-negative number k, returns 4 to the power of k, without using the * operator, or any loops!

The code actually is pretty simple, as long as you don’t forget to include the base case!

Essentially, every power k is 4 times the power before it, so we use the + operator 4 times, as we are restricted from using the multiplication operator!

Solution

int lotsOfFours(int k) {
  // k < 0 return an error!
  if (k < 0)
    return -1;   
  // Dont forget your base case!!!
  else if (k == 0)
    return 1;
  else
    return lotsOfFours(k-1) + lotsOfFours(k-1) + lotsOfFours(k-1) + lotsOfFours(k-1);
  // Essentially, for every 4 we add 4 of what we had before together!
}

Postfix Arithmetic Evaluation

Contributed by Tyler Carson.

You are given a postfix expression stored in a C-string consisting of single-digit positive integers and arithmetic operators. Write a function int evalPostfix(char* c), which evaluates the postfix expression contained in the C-string stored at c, and returns the resulting value.

  • You may declare your own structs or classes or use existing structures from the C standard library.
  • You may assume that for any initial operand x, 0 < x <= 9
  • You may assume that the arithmetic operations contained in c will be limited to {+, -, *, /}, and will be represented using their corresponding ASCII characters.
  • You may assume that the expression passed to your function is syntactically valid.

Example

 input:  {'1', '1', '+', '2', '-', '\0'}
 output: 0

 input:  {'5', '2', '/', '3', '*', '\0'}
 output: 6

Solution

#include <stack>

int evalPostfix(char* c) {
  std::stack<int> operands; 
  char* cur = c;
  while (*cur != '\0') {
    if (isdigit(*cur)) {
      operands.push(*cur-48);
    } else {
      int a = operands.top();
      operands.pop();
      int b = operands.top();
      operands.pop();
      switch (*cur) {
        case '+':
          operands.push(b+a);
          break;
        case '-':
          operands.push(b-a);
          break;
        case '*':
          operands.push(b*a);
          break;
        case '/':
          operands.push(b/a);
          break;
      }
    }
    cur++;
  }
  return operands.top();
}

Maximum Profit of a Stock

Contributed by Xiaoxu Wu.

The prices of a stock can be represented by an vector of integers, where the indices of the vector represent time, and the value at each index represents the price of the stock. Write a function that takes such a vector, and returns the maximum profit that could be made by buying and then selling the stock once.

You may assume the following:

  1. Price of the stock may vary from 0 to 1000 (inclusive)
  2. A profit can definitely be made

If you are unfamiliar with stock basics, here are some basic ideas:

  1. You may buy a stock at a certain price and sell it at a certain price. The return is the price you sell it at minus the price you buy it at. You want to maximize that value.
  2. Clearly, you have to buy a stock first before you can sell. You cannot sell before you buy.
  3. If you do understand stocks, you probably realized that this problem is oversimplified. Yes, we are only buying and selling one share of the stock. If you don't know what this means, don't worry about it.

Example

Input:
{100, 200, 500, 200, 1000}
Output: 
900

Input
{50, 100, 500, 200, 600, 300}
Output:
550

Solution

It is important to realize that we can maximize profits by iterating through the vector, taking the smallest value up to the index and the value at the index, and subtracting the former from the latter. We will update another integer variable, max, only if we find a value larger than what it is currently. We keep track of the smallest value up to the index with another integer variable, and we initiate it to be 1000, the largest possible value of a stock (as given in the problem).

#include <vector>
using namespace std;

int maxProfit(const vector<int>& stock) {
  int max = 0;
  int minSoFar = 1000;
  for (int i = 0; i < stock.size(); i++) {
    if (stock[i] < minSoFar)
      minSoFar = stock[i];
    else if (stock[i] - minSoFar > max) 
      max = stock[i] - minSoFar;
  }
  return max;
}

Merge

Contributed by Allison Ko.

Implement the merge function which, given two sorted arrays, merges them into one sorted array. Assume they are in non-decreasing order, and that inputs are valid (i.e. you don't have to check if the input arrays are actually sorted). Return a pointer to your merged array. Your solution should have O(n) time complexity.

int* merge(int list1[], int n1, int list2[], int n2) {
  // your code here
}

Example

Given list1 = {-3, 4, 30, 48, 52} and list2 = {-30, -17, 0, 2, 16} Return a pointer to the array {-30, -17, -3, 0, 2, 4, 16, 30, 48, 52}

Solution

int* merge(int list1[], int n1, int list2[], int n2) {
  int i = 0, j = 0, k = 0;
  int *result = new int[n1 + n2];

  while (i < n1 || j < n2) {
    if (i == n1) {
      result[k] = list2[j];
      k++;
      j++;
    } else if (j == n2) {
      result[k] = list1[i];
      k++;
      i++;
    } else if (list1[i] < list2[j]) {
      result[k] = list1[i];
      k++;
      i++;
    } else {
      result[k] = list2[j];
      k++;
      j++;
    }
  }
  return result;
}

Class Composition and a Little Polymorphism

Contributed by Hana Kim.

A class Dessert has derived class Pie, which has member variables Filling and Crust that are objects. What does the following code output?

#include <iostream>
using namespace std;

class Filling {
  public:
    explicit Filling(string type) {
      cout << "I am " << type << " pie." << endl;
    }
    ~Filling() {
      cout << "Spice" << endl;
    }
};

class Crust {
  public:
    Crust() {
      cout << "I'm crust." << endl;
    }
    ~Crust() {
      cout << "Flaky!" << endl;
    }
};

class Dessert {
  public:
    Dessert() {
      cout << "The best meal." << endl;
    }
    ~Dessert() {
      cout << "It's over." << endl;
    }
    virtual void eat() {
      cout << "Ouch." << endl;
    }
    void cook() {
      cout << "Burnt." << endl;
    }
};

class Pie : public Dessert {
  public:
    explicit Pie(string type)
    :myFilling(type) {
      cout << "Lovely pie!" << endl;
    }
    ~Pie() {
      cout << "All gone!" << endl;
    }
    virtual void eat() {
      cout << "Ow." << endl;
    }
    void cook() {
      cout << "Baked." << endl;
    }
  private:
    Filling myFilling;
    Crust myCrust;
};

void person(Dessert *d) {
  d->eat();
  d->cook();
}

int main() {
  Pie p("pumpkin");
  Dessert d;
  person(&d);
  person(&p);
}

Solution

The best meal.
I am pumpkin pie.
I'm crust.
Lovely pie!
The best meal.
Ouch.
Burnt.
Ow.
Burnt.
It's over.
All gone!
Flaky!
Spice
It's over.

Inheritance: Animal and Dog

Contributed by Kelvin Wong.

Write two classes: a base class called Animal that has a void function called speak() which prints out "hello" and a class called Dog that inherits from Animal and its speak() function prints out "hellohello". Dog's speak() function must not use cout.

Solution

#include <iostream>
using namespace std;

class Animal {
  public:
    void speak() {
      cout << "hello";
    }
};

class Dog : public Animal {
  public:
    void speak() {
      Animal::speak();
      Animal::speak();
    }
};

Recursive Cube Root Approximation

Contributed by Henry Yang.

Using recursion, find an approximation of the cube root of a double. The approximation should be within an error epsilon of the double when cubed. Only use control statements and basic arithmetic functions. Function signature: double cbrt(double d, double epsilon) NOTE: feel free to define a recursive helper function for cbrt to call!

Example

cbrt(27, 0.01) returns 3.0009 (for my implementation). Note that it doesn't have to be 3 -- it could be anywhere between 2.9 and 3.1.

Solution

This solution approximates the cube root in a binary search fashion, starting with a range from 0 to the double.

double cbrt_helper(double d, double low, double high, double epsilon) {
  double approx = (low + high) / 2;
  double error = d - approx*approx*approx;
  if (error < 0) {
    error = -error;
    if (error < epsilon)
      return approx;
    else
      return cbrt_helper(d, low, approx, epsilon);
  } else {
    if (error < epsilon)
      return approx;
    else
      return cart_helper(d, approx, high, epsilon);
  }
}

double cbrt(double d, double epsilon) {
  return cbrt_helper(d, 0, d, epsilon);
}

Inserting Elements Anywhere in a Doubly Linked List

Contributed by Michael Evangelista.

Given an unsorted doubly-linked list of integers, write a function insertValue that can insert a new integer in any position in the list. insertValue will take a Node pointer (passed by reference), a value to be inserted, and a position for the value to be inserted. Do not assume that position will be a valid position in the array.

Example

Here is the node structure:

struct Node {
  int value;
  Node* next;
  Node* prev;
};

Given a doubly linked list of the following elements: 1, 2, 3, 4, 5, 6, here is some example input.

insertValue(head, 10, -1);  // Should fail
insertValue(head, 20, 6);  // Should fail
insertValue(head, 30, 3);  // Should work, list should now be 1, 2, 3, 30, 4, 5, 6
insertValue(head, 40, 0);  // Should work, list should now be 40, 1, 2, 3, 30, 4, 5, 6
insertValue(head, 50, 4);  // Should work, list should now be 40, 1, 2, 3, 30, 50, 4, 5, 6
insertValue(head, 60, 8);  // Should work, list should now be 40, 1, 2, 3, 30, 50, 4, 5, 60, 6
insertValue(head, 70, 20);  // Should fail.

Solution

void insertValue(Node* &head, int value, int position) {
  if (head == nullptr)
    return;  // Check if list is empty
  if (position < 0)
    return;  // Check if position is negative
  
  if (position == 0) {  // If it just wants us to insert at head of the list
    Node *insert = new Node;
    insert->value = value;
    insert->next = head;
    insert->prev = NULL;
    head->prev = insert;
    head = insert;
    return;
  }
  
  // Iterate through list until position is reached
  Node* ptr = head;
  int count = 0;
  while (ptr != nullptr && count != position) {  
    // Go until at desired position OR hit end of list
    ptr = ptr->next;  // Set to next position
    count++;
  }
  if (ptr == nullptr) {  // If true, then we hit the end of the list
    return;
  } else {  // If here, then the loop broke because we are at the correct position
    Node* insert = new Node;
    insert->value = value;
    insert->next = ptr;
    insert->prev = ptr->prev;
    ptr->prev->next = insert;
    ptr->prev = insert;
  }
}

Binary Search Tree to Linked list

Contributed by Richard Yu.

Given a binary search tree with numbers already input form a sorted linked list. It may call other functions you write. Which traversion will you use through the binary search tree?

Example

Given the implementation of the Tree and List nodes:

struct TreeNode {
  int val;
  TreeNode* leftChild;
  TreeNode* rightChild;
  explicit TreeNode(int val) {
    this.val = val;
    leftChild = nullptr;
    rightChild = nullptr;
  }
};

struct ListNode {
  int val;
  ListNode* next;
  explicit ListNode(int val) {
    this.val = val;
    next = nullptr;
  }
};

Solution

void inOrder(TreeNode* currNode, ListNode* head) {
  if (currNode->leftChild != nullptr) {
    inOrder(currNode->leftChild);
  }
    
  if (head == nullptr) {
    head = new ListNode(currNode->val);
  } else {
    ListNode* curr = head;
    while (curr->next != nullptr) {
        curr = curr->next;
    }
    curr->next = new ListNode(currNode->val);
  }
      
  if (currNode->rightChild != nullptr) {
    inOrder(currNode->rightChild);
  }
}

ListNode* treeToList(TreeNode* treeHead) {
  ListNode* listHead = nullptr;
  // Calls in-order traversal
  inOrder(treeHead, listHead);
  return listHead;
}

Reverse Linked List

Contributed by Xueyang Feng.

Given pointer to the head node of a linked list, the task is to reverse the linked list.

Example

Input : Head of following linked list
1->2->3->4->NULL Output : Linked list should be changed to, 4->3->2->1->NULL

Input : Head of following linked list
1->2->3->4->5->NULL Output : Linked list should be changed to, 5->4->3->2->1->NULL

Input : NULL Output : NULL

Input : 1->NULL Output : 1->NULL

Solution

#include<stdio.h>
#include<stdlib.h>

/* Link list node */
struct node {
  int data;
  struct node* next;
};

/* Function to reverse the linked list */
static void reverse(struct node** head_ref) {
  struct node* prev = NULL;
  struct node* current = *head_ref;
  struct node* next;
  while (current != NULL) {
  next = current->next;
  current->next = prev;
  prev = current;
  current = next;
  }
  *head_ref = prev;
}

/* Function to push a node */
void push(struct node** head_ref, int new_data) {
  /* allocate node */
  struct node* new_node =
  (struct node*) malloc(sizeof(struct node));

  /* put in the data  */
  new_node->data = new_data;

  /* link the old list off the new node */
  new_node->next = (*head_ref);

  /* move the head to point to the new node */
  (*head_ref) = new_node;
}

/* Function to print linked list */
void printList(struct node *head) {
  struct node *temp = head;
  while (temp != NULL) {
  printf("%d  ", temp->data);
  temp = temp->next;
  }
}

/* Driver program to test above function*/
int main() {
  /* Start with the empty list */
  struct node* head = NULL;

  push(&head, 20);
  push(&head, 4);
  push(&head, 15);
  push(&head, 85);

  printf("Given linked list\n");
  printList(head);
  reverse(&head);
  printf("\nReversed Linked list \n");
  printList(head);
  getchar();
}

Linked Set

Contributed by Wandi Liu

Given the following skeleton of a singly-linked-list class, implement a function insert() that:

  • takes in a new int
  • checks if it's already in the set (is a duplicate), if so, return false.
  • inserts the new int into the set, sorted in ascending order, from smallest to largest.
  • return true if the int was inserted
#include <iostream>
using namespace std;

class SLL{
 public:
    SLL() {head = nullptr;}
    bool insert(int new_num) {
        Node* ptr = head;
        // YOUR CODE HERE
            return true;
    }
    
 private:
    struct Node{
     public:
        explicit Node(int n) : m_num(n) { // node is initalized to NULL
            m_next = nullptr;
        }
        int get_num() {return m_num;}
        Node* m_next;
     private:
        int m_num;
    };
    Node* head;
};

Example

int main() {
  SLL c;
  c.insert(3);  // inserts & returns true
  c.insert(5);  // inserts & returns true
  c.insert(8);  // inserts & returns true
  c.insert(4);  // inserts & returns true
  c.insert(5);  // already in set, returns false!
}

####### c should now contain: {3,4,5,8}

Solution

class SLL{
 public:
    SLL() {head = nullptr;}
    bool insert(int new_num) {
        Node* ptr = head;
        if (ptr == nullptr) {  // edge case: if the set was empty
            Node* new_node = new Node(new_num);
            head = new_node;
            return true;
        }
        while (ptr->m_next && ptr->m_next->get_num() < new_num) {
            // while the number isn't the largest
            // and the next number is smaller than the new one
            ptr = ptr->m_next;  // go to the next number
        }
        if (!ptr->m_next) {
            // if we're at the end of the set --
            // (biggest number, but still smaller than the new one),
            // insert the new number at the end
            Node* new_node = new Node(new_num);
            ptr->m_next = new_node;
            return true;
        } else if (ptr->m_next->get_num() == new_num) {
            // if new_num is the same as next number in the set, don't insert it
            return false;
        }  // else, insert the new node before the next number!
            Node* new_node = new Node(new_num);
            Node* tmp = ptr->m_next;
            ptr->m_next = new_node;
            new_node->m_next = tmp;
            return true;
    }
    
 private:
    struct Node{
     public:
        explicit Node(int n) : m_num(n) { // node is initalized to NULL
            m_next = nullptr;
        }
        int get_num() {return m_num;}
        Node* m_next;
     private:
        int m_num;
    };
    Node* head;
};

Symmetric Binary Tree

Contributed by Taoran Liu.

Given a pointer to a node of a binary tree, return true if the tree is symmetric, and false otherwise. Assume that an empty binary tree is symmetric. Try to solve this recursively.

Example

1
/ \
2   2
/ \ / \
3  4 4  3

true

1
/ \
2   2
/ \ / \
3  4 3  4

false

1
/ \
2   2
\   \
3    3

false

Solution

#include <iostream>

using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    explicit TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

bool ismirror(TreeNode *p, TreeNode *q) {
    if (!p&&!q) return true;
    else if (!p||!q) return false;

    if (p->val == q->val) return ismirror(p->left, q->right) && ismirror(p->right, q->left);
    else
        return false;
}

bool isSymmetric(TreeNode* root) {
    if (!root) return true;

    return ismirror(root->left, root->right);
}



int main() {
    TreeNode* tree;
    tree[0] = TreeNode(1);
    tree[1] = TreeNode(2);
    tree[2] = TreeNode(2);
    tree[3] = TreeNode(3);
    tree[4] = TreeNode(3);
    tree[5] = TreeNode(4);
    tree[6] = TreeNode(4);

    tree[0].left = &tree[1];
    tree[0].right = &tree[2];
    tree[1].left = &tree[3];
    tree[1].right = &tree[5];
    tree[2].left = &tree[6];
    tree[2].right = &tree[4];

    cout << isSymmetric(&tree[0]);

    return 0;
}

Recursive Word Search

Contributed by Changfei Shi.

Given a 5x5 character array, a target string, and a row and column to start from, write a recursive function to determine whether a word can be found by starting at the specified row and column(where the last letter of the word is found) and moving only upward and to the left.

Example

The function should return true for the target string "helloworl" and the character array input hefgz mlndb rlofn lrwvd zzorl The function should return false for the same target string and the character array input hnfgz mlndb rlofn lrwvd zzorl

Solution

bool recursiveWordSearch(char c[][5], string s, int row, int col) {
    if (s.length() == 0)  // An empty string is trivially in the 2d array
        return true;
    if (row < 0 || col < 0)  // Past the bounds of the search, return false
        return false;
    if (c[row][col] == s[s.size() - 1]) {
        s = s.substr(0, s.size() - 1);
        bool val1 = recursiveWordSearch(c, s, row - 1, col);
        bool val2 = recursiveWordSearch(c, s, row, col - 1);
        return val1 || val2;
    } else {
        return false;
    }
}

Merge Intervals

Contributed by Regan Hsu.

Given a collection of intervals, merge all overlapping intervals.

Example

For example, Given [1,3],[2,6],[8,10],[15,18], return [1,6],[8,10],[15,18].

Solution

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

struct Interval {
     int start;
     int end;
     Interval() : start(0), end(0) {}
     Interval(int s, int e) : start(s), end(e) {}
};

static bool my_cmp(const Interval &a, const Interval &b) {
    return a.start < b.start;
}

vector<Interval> merge(vector<Interval> intervals) {
    vector<Interval> myVec;
    sort(intervals.begin(), intervals.end(), my_cmp);
    for (int i = 0; i < intervals.size(); i++) {
        int begin = i;
        int j = i+1;
        while ((j < intervals.size()) && (intervals[i].end >= intervals[j].start)) {
            if (intervals[i].end >= intervals[j].end) 
                intervals[j].end = intervals[i].end;
            i++;
            j++;
        }
        if (begin == i) {
            myVec.push_back(intervals[i]);
        } else {
            Interval ugh;
            ugh.start = intervals[begin].start;
            ugh.end = intervals[i].end;
            myVec.push_back(ugh);
        }
    }
    return myVec;
}

Recursive binary search on an array

Contributed by Robert Zalog

Implement the function provided by the following function header:

int findNum(int *nums, int n, int num);,

which returns the index of a given number num in a sorted (in ascending order) array nums of length n. Your function must not use a for loop and must utilize a recursive function call. In addition, your algorithm must run in O(log n) time complexity. You can assume that the specified value will always be found in the array (e.g., function caller will not ask you to look for 3 in an array that does not contain a 3).

Hint:

You might want to use a helper function that takes a start and an end parameter instead of just n.

Example

Example function call:

int nums[6] = {1, 2, 4, 8, 10, 18};
findNum(nums, 0, 8); // returns 3

Solution

int findNumHelper(int *nums, int start, int end, int num);

int findNum(int *nums, int n, int num)
{
        return findNumHelper(nums, 0, n, num);
}

int findNumHelper(int *nums, int start, int end, int num)
{
        int test = start + (end - start) / 2;
        if (nums[test] == num) {
                return test;
        }
        if (nums[test] > num) {
                return findNumHelper(nums, start, test, num);
        }
        if (nums[test] < num) {
                return findNumHelper(nums, test+1, end, num);
        }
}

Ways to Count

Contributed by Lucas Tecot.

You are given a whole number and must count up to it in increments of 1 and 2. Find the number of ways you can count to that number.

Example

For the number 3, we return 3. (1+1+1, 1+2, or 2+1)

For the number 4, we return 5. (1+1+1+1, 1+1+2, 1+2+1, 2+1+1, 2+2)

Solution

It turns out that this problem is essentially just fibonacci numbers. You can do it with recursion but using a loop is much more efficient.

int numCounts(int n) {
  if (n <= 0) 
    return 0;
  if (n <= 2) 
    return n;
  int p2 = 1;
  int p1 = 2;
  int total = 0;
  for (int i = 3; i <= n; i++) {
    total = p1 + p2;
    p2 = p1;
    p1 = total;
  }
  return total;
}

Repeat Finder

Contributed by Bibek Ghimire.

Write a function that takes as input a string of arbitrary length and returns a vector of all substrings of length 4 that appear more than once within the input string.

The function declaration should look like: vector<string> findRepeats(string s);

Your function must run in O(N) time, where N is the length of the input string.

Example

vector<string> repeats = findRepeats(“ABCABCADEFADEFA”); // repeats contains [“ABCA”, “ADEF”, “DEFA”]

Solution

#include <iostream>
#include <string>
#include <vector>
#include <unordered_set>
using namespace std;

vector<string> findRepeats(string s) {
    unordered_set<string> substrings;
    unordered_set<string> matches;
    const int size = s.size();
    const int length = 4;

    // Start out with first substring to test against
    substrings.insert(s.substr(0, length));

    for (int i = 1; i <= (size - length); i++) {
        string currSub = s.substr(i, length);

        // Current substring exists earlier in the string
        if (substrings.find(currSub) != substrings.end()) {
            matches.insert(currSub);
        }

        substrings.insert(currSub);
    }

    vector<string> m;
    for (unordered_set<string>::iterator it = matches.begin();it != matches.end(); it++) {
        m.push_back(*it);
    }

    return m;
}

int main() {
    // cout >> findRepeats("ABCABCADEFADEFA");
    vector<string> m = findRepeats("ABCABCADEFADEFA");
    for (int i = 0; i < m.size(); i++) {
        cout << m[i];
    }
}

Choosing the Right Container

Contributed by Eric Tan.

For each situation, choose the most appropriate data structure from the following C++ STL containers:

  • list, stack, queue, set, unordered_set, map, unordered_map

Then list the time complexity of performing the action specified in each situation. Explain why the container you chose is appropriate.

  1. A bank wants to keep a catalogue of all of its customers' names. It frequently adds new customers to its catalogue and searches for existing customers' names. It also wants to maintain alphabetical ordering of the customers by last name. Which STL container should be used, and what is the time complexity of finding a certain customer in a catalog of n customers?

  2. A school wants to keep track of the name and ID number for each of its students. The student population changes relatively little over time. The school wants to be able to quickly and frequently search up a student's ID number given a student's name. Which STL container should be used, and what is the time complexity of finding a student's ID number if the school has k students?

  3. A company that makes gaming consoles has sold out on its most popular console, and it wants to keep a wait list for people who wish to buy the console when more are in stock. People who reserve a spot on the wait list earlier should be the first ones to obtain the console once more are released. What STL container should be used, and what is the time complex- ity of finding a certain person's position on the wait list, assuming there are m people on the wait list?

Solution

  1. set, O(log(n)). A set is typically implemented as a binary search tree. A BST is capable of having an unlimited size (without impacting performance), and it uses only as much space as it needs (one per element). In addition, it maintains an ordering on the elements, as needed for the customer's last name.

  2. unordered_map, O(1). An unordered_map is essentially a hash table that maps a key to a value, which is appropriate for pairing a student's name with his or her ID number. On average, a (well-designed) hash table can search up a key in constant time. Since the student population remains roughly the same, there is no need to worry about expanding the size of the hash table or any impact size expansion may have on its performance. Also, there are no requirements on any ordering.

  3. queue, O(m). A queue is a FIFO data structure, which makes sense for this situation because the people who get on the wait list first should get off the wait list first when the console restocks.


Check if a tree is a BST

Contributed by Caroline Quigg.

Write a function: bool isBST(Node* root).

This function will be used to determine if a tree is a binary search tree or not. Assume that the convetion we are using for BST is that values less than or equal are on the left and values strictly greater than are on the right.

One may any implement auxiliary functions needed to perform this task.

Solution

The idea behind the solution is that the children of a node should fall into a range depending on its ancestors. For example, the left child of any given node should be less than or equal to its parent, but it must also be less than its parent's parent and so on. So we keep track of the range a child node's value by keeping track of a max and min value, which we update as we recurse.

#include<climits>
struct Node{
    int value;
    Node* left;
    Node* right;
};


bool isBSTHelper(Node* root, int min, int max) {
    if ( root == nullptr)
        return true;
    
    if ((root->value <= min) || (root->value > max)) {
        return false;
    }
    
    if (!isBSTHelper(root->left, min, root->value) ||
        !isBSTHelper(root->right, root->value, max)) {
        return false;
    }
    
    return true;
}

bool isBST(Node* root)  {
    return isBSTHelper(root, INT_MIN, INT_MAX);
}

Minimum Depth of a Binary Tree

Contributed by Hye Won (Helen) Lee.

Find the minimum depth of a binary tree. The minimum depth is the lowest level of a tree, starting from the root node.

Solution

struct Node { int val; Node* left; Node* right; };
int minDepth(Node* root) {
    if (root == nullptr) return 0;
    if (root->left == nullptr && root->right == nullptr) return 1;
    if (!root->left) return minDepth(root->right) + 1;
    if (!root->right) return minDepth(root->left) + 1;
    return min(minDepth(root->left), minDepth(root->right)) + 1;
}

A Reference or a Pointer?

Contributed by Nikhil Kansal.

You are given the following code snippet.

#include <iostream>

class Base {
 public:
    Base(int, int&, int);
    virtual ~Base();
    virtual void print() const {
        std::cout << a << ", " << b << ", " << *c << std::endl;
    }
 private:
    int a;
    int& b;
    int* c;
};

/*
 * Implement the constructor and destructor of Base here
 */

class Derived : public Base {
 public:
    Derived(int, int&, int);
    virtual ~Derived();
    virtual void print() const {
        std::cout << "Called from Derived: " << std::endl;
        Base::print(); 
    }
};

/*
 * Implement the constructor and destructor of Derived here
 */

int main() {
    int x = 10;
    Base b(5, x, 15);
    b.print();

    int y = 25;
    Derived d(20, y, 30);
    d.print();

    return 0;
}

Assume that everything written already is correct. Your job is to only implement the constructors and destructors of the Base and Derived classes such that running the program outputs exactly the following:

Constructing Base Class
5, 10, 15
Constructing Base Class
Constructing Derived Class
Called from Derived:
20, 25, 30
Destructing Derived Class
Destructing Base Class
Destructing Base Class

You may not change any of the written code. Only add code in the commented areas of the following code snippet.

Solution

// Notice the use of the initializer list to create the
// Base class, and also to assign the reference variable.

#include <iostream>

class Base {
 public:
    Base(int, int&, int);
    virtual ~Base();
    virtual void print() const {
        std::cout << a << ", " << b << ", " << *c << std::endl;
    }
 private:
    int a;
    int& b;
    int* c;
};

Base::Base(int _a, int& _b, int _c) : a(_a), b(_b) {
    std::cout << "Constructing Base Class" << std::endl;
    c = new int;
    *c = _c;
}

Base::~Base() {
    std::cout << "Destructing Base Class" << std::endl;
    delete c;
}

class Derived : public Base {
 public:
    Derived(int, int&, int);
    virtual ~Derived();
    virtual void print() const {
        std::cout << "Called from Derived: " << std::endl;
        Base::print(); 
    }
};

Derived::Derived(int _a, int& _b, int _c) : Base(_a, _b, _c) {
    std::cout << "Constructing Derived Class" << std::endl;
}

Derived::~Derived() {
    std::cout << "Destructing Derived Class" << std::endl;
}

int main() {
    int x = 10;
    Base b(5, x, 15);
    b.print();

    int y = 25;
    Derived d(20, y, 30);
    d.print();

    return 0;
}

Inorder Tree Traversal

Contributed by Shirley He

Given the root pointer to a binary search tree, implement the following function to print the tree in-order (use recursion):

  • void inOrder(Node* root);

Example

Suppose level order of the tree : A / B C / D E F G / H I J K L

Inorder : H D I B J E K A L F C G

Solution

#include <iostream>
using namespace std;

struct Node {
    int key;
    Node* left;
    Node* right;
};

void inOrder(Node* root) {
    if ( root ) {
        inOrder(root->left);
        cout << root->key << " ";
        inOrder(root->right);
    }
}

int main() {
    Node* root;
    root->key = 10;
    root->left = new Node;
    root->left->key = 20;
    root->left->left = nullptr;
    root->left->right = nullptr;
    root->right = nullptr;
    
    inOrder(root);
    return 0;
}

Inheritance and Polymorphism Code Tracing

Contributed by Michael Germano.

Given the following classes and main function, find the integer result.

class foo {
public:
    explicit foo(int x) : y(x) {
        if (y % 2 == 0) {
            y *= 4;
            y-= 1;
        } else {
            y *= 3;
        }
    }
    virtual int doSomething() {
        y -= 3;
        return y;
    }
private:
    int y;
};

class bar : public foo {
public:
    explicit bar(int x): foo(x * 2 + 1), x(x) {}
    virtual int doSomething() {
        int f = foo::doSomething();
        x *= f;
        return x;
    }
    
private:
    int x;
};

int main() {
    foo * a = new bar(3);
    foo b(4);
    int result = a->doSomething() - b.doSomething();
    
    // What is result?
    delete a;
}

Solution

result == 42

Starting at main, we create foo *a that points to a dynamically allocated bar object called a. We first enter bar's constructor for a. Here we construct foo with value 7, since 3 * 2 + 1 = 7.

We then enter foo's constructor. Since 7 is odd, we multiply it by 3 (y is now 21 for a). Now we set x for a to 3 and our construction for a is finished.

Next we create b, constructing it with value 4. Since 4 is even we multiply by 4 and subtract 1 (y is now 15 for b).

We then we calculate a->doSomething(). Since this function is virtual, we call the function for the bar class. This function then calls foo::doSomething(); which returns 18 since 21 - 3 = 18.

Next we multiply x (which is 3) by this result which gives 3*18 = 54 and we return this value.

For the b.doSomething() function call, we simply subtract 3 from our y value (15) and return this value (12). Lastly we set our result integer to the difference between these two values: result = 54 - 12 = 42 and we are done.


Clone this wiki locally