PE2 Review

Important Functions

Array

Define a Fixed length 2-D array

long dir[8][2] = {{1, -1}, {1, 1}, {-1, 1}, {-1, -1}, {0, -1}, {0, 1}, {1, 0}, {-1, 0}};

Numbers

is_prime()

Return whether a number is a prime or not. Time complexity is O(N)O(\sqrt{N}).

bool is_prime(long num)
{
  for (long i = 2; i * i <= num; i += 1)
  {
    if (num % i == 0)
    {
      return false;
    }
  }
  return true;
}

count_factors()

Return the number of prime factors of a num. Time complexity is O(N)O(\sqrt{N})

Strings

is_match()

char *word is your source string, size_t i is the position in word you want to start searching for. char *search_for is the string that you want to search for in word.

The use of i here is awesome! We won't be afraid that our pointer to the string will be moved away!

substitute()

An intermediate function that replace the target string with the replace string plus white spaces.

Here it is assumed that the length of the target string is longer than or equal to the length of the replace string.

compact()

An intermediate function that takes in the source string word and reform the string by ignoring the white space in it.

Based on the same assumption above, our dst is always smaller than or equal to src

replace()

A complete function that uses is_match(), substitute() and compact() above to achieve the purpose that after the execution of the function, all the serach_for substrings that have appeared in the source string will be replaced with the replace_with string.

My Solution for 5. Substring*

The classic one:

Binary Search for the position

Instead of returning -1 if the query q is not found, modify the binary search algorithm such that it returns either:

  • a position k, such that list[k] <= q <= list[k+1].

  • -1 if q < list[0]

  • n - 1 if q > list[n-1]

Binary Search in a Rotated Sorted List

Appeared in 3. Rotate*

Where, within_range() is implemented as follows;

Binary Search to get the length of "#"

Appear in 4. Box* (AY21/22) and 4. Mode*(AY23/24)

  1. Recursive Method

  1. Iterative Method

Counting Sort

This is the only sorting algorithm that has the chance to take O(N)O(N) to sort a list.

Selection Sort

Time complexity is O(N2)O(N^2)

The soul of this algorithm is to 1) partition the list into two parts, an unsorted part followed by a sorted part, 2) repeatedly selects the maximum element from the unsorted part and move it to the front of the sorted part. (For increasing sort).

Otherwise, for decreasing sort, the idea will be to find the smallest unsorted element and add it to the end of the sorted list.

Insertion Sort

Similar to Selection Sort*, now we partition our list into 1) a sorted one, 2) followed by an unsorted one. Then we repeatedly take the first element from the unsorted partition, find its rightful place in the sorted partition, and insert it into place. We start with a sorted partition of one element, and we end if the sorted partition contains all the elements.

  • Take the first element X from the unsorted partition

  • use binary search to find the correct position to insert X

  • insert X into the right place

Advanced Recursion

Permutation

NQueens - Find all solutions

NQueens - Find one solution quicker

Standard C Libaray

ctype.h

Function name
Description

isalpha(char c)

check whether c is alphabetic or not

isdigit(char c)

check whether c is a decimal digit or not

islower(char c)

check whether c is a lowercase letter

ispunct(char c)

check whether c is a punctuation or not

isupper(char c)

check whether c is an uppercase letter

tolower(char c)

convert uppercase letters to lowercase

toupper(char c)

convert lowercase letters to uppercase

Punctuation letters: This is a set of ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~

Tips

  1. When doing string traversal, it is strongly recommended to use strlen() to get the length of the string, and then use a for loop to traverse through thes string, with the loop variable i indicating the current position of the character we have traversed!

  2. Refer back to Lab 09 - Backtracking when doing the backtracking problems! Usually, an easier way to help you understand is to draw a "tree".

  3. The 3. Group* provides an awesome idea to use array to store the previous states when doing backtracking!

  4. When writing recursion in 2-D array, always think about how would you not enter an "infinite loop". This is usually down in your condition to enter the recursion. Some common methods are:

    1. mark the attendance of the "cell" you have updated. (a.k.a build an unvisited_array)

    2. there is some initial "constant" that you can compare to

  5. When doing Backtracking/Recursion problems, always think about the three statements, they will help you form the solution: a)Current Stage, b)Terminating Condition, c)State Transitions. Anyway, the whole idea is to think about how to do the backtracking! (State Transitions). This is usually done by:

    1. either redo the step you have done

    2. write a new value to the step you have done

  6. Somtimes changing the loop condition will change the obvious time complexity, pay attention to the "hidden" time complexity and sometimes this kind of change can be utilised to make your code more effificient. See 2. Sun

  7. When you want to improve the complexity of searching/sorting problems,

    1. try thinking about how to narrow your "searching area". This will be very useful!

    2. think about find the pattern, this will affect your algorithm greatly. See Exercise 6 - Searching and Sorting

  8. The strlen() from C standard lib <string.h> will return the number of characters in a string (excluding the terminating '\0').

  9. Whenever you see the Time complexity is O(logN)O(logN), try to think of binary search.

  10. When implementing the search algorithm, always keep in mind:

    1. How to define our search range (The use of index is inclusive or not)

    2. When to stop our searching (How to decide the search is successful or not)

    In the classic Binary Search, our search range is all the number bewteen list[i] and list[j] (both inclusive). And there are two cases we should stop our searching: 1) when there is no element in our search range, 2) when list[mid] is what we want to find.

Valuable Problems from Past Year

Below are the valueable problems I think are important or classic

Valueable Problems from Past Year

Here the number refers to the exact pages in the corresponding past year papers' comments version.

Last updated