</>CodexBash
Learn
First stepsBeginner10 min

Arrays and lists in everyday code

Fixed and growable arrays, returning one to the judge, sorting with the built-in sort, and building grids without the classic Python trap.

Read these first

1 of 1 still to read
  1. Decisions and loops
An array in memorystep 1/5
1000
4
[0]
1004
9
[1]
1008
2
[2]
1012
7
[3]
1016
5
[4]

 

An array is a promise: these values sit in houses next to each other, starting at one address.

Most problems hand you an array and ask for something about it. This lesson is the everyday toolkit: making arrays, growing them, sorting them and handing one back. How arrays are laid out in memory, and why that makes them fast, comes in a later lesson.

Fixed size or growable#

Every language has two kinds: one whose size is fixed when it is made, and one that grows as you add to it.

// Fixed: ask for the memory yourself.
int* squares = malloc(n * sizeof(int));
for (int i = 0; i < n; i++) squares[i] = i * i;

// Growable: C has none built in. Allocate the most you could need,
// and keep your own count of how many are used.
int* evens = malloc(n * sizeof(int));
int count = 0;
for (int i = 0; i < n; i++) {
    if (nums[i] % 2 == 0) evens[count++] = nums[i];
}

Adding to the end of a growable array is fast, one step on average. Adding to the front is not: everything has to shift along by one. If you find yourself inserting at the front in a loop, build the array backwards and reverse it once at the end.

Handing an array back to the judge#

When a problem returns an array, the growable kind is often the easiest to build, but the signature may ask for the fixed kind.

// Allocate, fill, and say how many you filled.
int* answer = malloc(count * sizeof(int));
for (int i = 0; i < count; i++) answer[i] = evens[i];
*returnSize = count;
return answer;

Sorting#

You will rarely write your own sort. Each language has one that takes about n log n steps, which for 100,000 numbers is under two million.

int ascending(const void* a, const void* b) {
    int x = *(const int*) a, y = *(const int*) b;
    return (x > y) - (x < y);
}

qsort(nums, numsSize, sizeof(int), ascending);

In C, write the comparison as (x > y) - (x < y) rather than the tempting x - y. The subtraction overflows for large values of opposite sign and sorts them the wrong way round.

Grids#

A grid is an array of rows. Position [r][c] is row r, column c.

int** grid = malloc(rows * sizeof(int*));
for (int r = 0; r < rows; r++) {
    grid[r] = calloc(cols, sizeof(int));     // calloc fills with zeros
}

The Python trap in that last comment is one of the most asked questions about the language. The list comprehension builds a fresh row each time; multiplying the outer list copies a reference to one row.

Useful one-liners#

To findC++JavaPython
the largest*max_element(v.begin(), v.end())Arrays.stream(a).max().getAsInt()max(a)
the totalaccumulate(v.begin(), v.end(), 0LL)Arrays.stream(a).asLongStream().sum()sum(a)
reversedreverse(v.begin(), v.end())loop, swapping from both endsa[::-1] or a.reverse()

In C you write each of these as a short loop, which is no bad thing: you can see exactly what it costs.

Try it#

Move zeroes asks you to rearrange an array in place, keeping the order of the non-zero values. Pascal's triangle returns a grid whose rows have different lengths, which is good practice at building one row at a time.

Practise it

The same idea, in the order it is worth meeting it.

  1. Not startedMove the zeroes to the endEasy
  2. Not startedBuilding Pascal's triangle row by rowEasy
  3. Not startedRunning sumEasy
Create a free account to track your progress