As a developer preparing for interviews with FAANG companies, I found myself struggling with simple algorithms like string traversal and palindrome checks. However, I persevered and, after nine months of hard work, was able to master even more specific algorithms like KMP. During this time, I relied on a notebook and pen to visualise how sorting algorithms work and how numbers are compared.
When I began preparing for interviews with FAANG companies, I struggled with simple algorithms such as String traversal and palindrome checks. There were times when I almost gave up, but I have always been one to finish what I start. The same approach was applied here, and after nine months of hard work, I went from struggling with simple algorithms to understanding more specific ones like KMP (which I like a lot).
On my journey to master these algorithms, I used a notebook and pen to visualise how sorting works, how numbers are compared, and where it all goes. This helped me to better understand the algorithms and improved my ability to work with them.
So why not create a project that visualises sorting algorithms in a more user-friendly way? Additionally, writing algorithmic solutions in a different language provides an extra opportunity to better understand and learn them.
I took advantage of this opportunity to improve my knowledge and develop a stronger understanding of the sorting pathway. By creating a mobile application using Flutter, I was able to utilise my experience with cross-platform development to build an effective tool for visualising complex algorithms, particularly sorting. This allowed me to further improve my knowledge and understanding of these algorithms while also creating a user-friendly platform for others to do the same.
With solid experience in developing cross-platform applications using the Flutter framework, I chose to utilise it to create a mobile application for both Android and iOS operating systems. Currently, the same code can run on web and desktop platforms if I add support.
During the process I achieved:
Each sorting algorithm is a descendant of BaseSort, which, in turn, is a ChangeNotifier. The details of each algorithm’s implementation are covered under its specific implementation: BubbleSort, HeapSort, InsertionSort, MergeSort, and SelectionSort. BaseSort only covers the basic parts of each algorithm, such as the references of left and right pointers, as well as the index of the sorted part. This class is responsible for generating random data and notifying each subscriber of a new dataset.
class BaseSort with ChangeNotifier {
BaseSort() {
generateData();
}
List<int> array = List.empty(growable: true);
int left = -1;
int right = -1;
int sorted = -1;
bool isSorting = false;
@mustCallSuper
void generateData() {
array.clear();
isSorting = false;
int counter = 0;
final rand = Random();
left = -1;
right = -1;
sorted = -1;
while (counter < 50) {
// to show anything in case of 0 -> shifting it to 1
array.add(rand.nextInt(99) + 1);
counter++;
notifyListeners();
}
}
Future startSorting() async {}
Future sleep() async {
await Future.delayed(const Duration(milliseconds: 150), () {});
}
}
BaseSortWidget is an abstract class that represents a collection of common widget parts, with several abstract methods to be implemented in each specific algorithm widget.
abstract class BaseSortWidget extends StatelessWidget {
@override
Widget build(BuildContext context) => Card(
margin: const EdgeInsets.all(8.0),
elevation: 2.0,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
algorithmName(),
style: const TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
const SizedBox(height: 10),
consumerWidget(),
const SizedBox(height: 10),
Text(
algorithmComplexity(),
style: const TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
],
),
),
);
}
Each algorithm widget implementation, with the exception of SelectionSort, is simplified to a state of:
class HeapSortWidget extends BaseSortWidget {
@override
String algorithmName() => HEAP_SORT;
@override
String algorithmComplexity() => 'Time: O(n*log(n)) Space: O(1)';
@override
Widget consumerWidget() => Consumer<HeapSort>(
builder: (context, state, _) => Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: buildItemsArray(
state.array,
state.left,
state.right,
state.sorted,
Colors.cyan,
),
),
);
}
All the other parts are merely for aesthetic purposes, to create a cleaner and more elegant code. The main screen is a list of sorting widgets.
Consumer<SortHolder>(
builder: (context, types, _) {
final List<Widget> widgets = types.generateWidgets(context);
return widgets.isEmpty
? Center(
child: Text(
'$DRAWER_TITLE\n\n$EMPTY_MESSAGE',
textAlign: TextAlign.center,
style: Theme.of(context)
.textTheme
.bodyLarge
.copyWith(fontSize: 18.0),
),
)
: ListView(
padding: const EdgeInsets.all(8),
children: widgets,
);
},
)
Whenever we add or remove widgets, the screen updates with more or fewer items. To hold data about widgets and to shuffle data/start sorting, we used SortHolder.
The resulting view of my work looks very neat and is easily understandable.
Observing the sorting process is a true pleasure. Additionally, it is an easier way to understand the sorting algorithm by seeing which data is being compared. The left pointer is represented by yellow, while the right pointer is represented by red. Enjoy!
While preparing to algorithmic and data-structure interviews it might be tricky to master these complex topics. People are using different approaches to make is simpler, and easier to understand. Having no whiteboard, which could help me to visualise data, I have found simple notebook and pen quite useful, but for automatisation of the process and to repeat algorithms again, I have used coding, one instrument I am good at. Now we can observe how these algorithms are working. But I would love to extend this knowledge base with other more complex algorithms, which might be even harder to visualise. But still possible.
I am calling everyone, who want to participate in this project, to contribute to my gitHub via pull requests. I am happy to dedicate time for short catch-ups and collaboration.