This document is discussed with @hsins.
See the definition of Convention over configuration in Wikipedia.
- Class:
UpperCamelCase - Function:
lowerCamelCase - Variable:
lowerCamelCase - Constant:
UPPERCASEwith underline - Field:
lowerCamelCase - Database:
SELECT * FROM name_table
// Class
class MyClass { ... }
// Function
function myFunction() { ... }
// Variable
int myVariable;
// Constant
#define MY_CONSTANT;
// Database Table
SELECT * FROM my_table-
There should only be one public function.
-
Declare the variables in the proper scope as slow as possible.
- Declare
ansas soon as possible. - Since LeetCode is just an online judge system rather than a big project, we don't scatter all variables in different sections. However, we still sort the variables based on the time we first use each of them.
- Declare
-
Code section (there should be one blank line between each sections.)
-
public- boundary conditions
- initial variables
- There may be many kernels separated with one blank line, but there shouldn't be any blank line in each kernel.
- return
-
private- private variables
- private function(s)
-
We use C++ to demo the idea.
Blank one single line between each section. However, if there’s no sec 12, no blank line between sec 11 and sec 13.
class Solution {
public:
// There should only be one public function.
func() {
// (sec 0) boundary conditions
// (sec 1) initial variables
// (sec 10) constexpr/const (size/length)
// (sec 11) ans
// (sec 12) declaration & operation
// (sec 13) purely declaration
// (sec 2) kernels
// (sec 3) modify original initial variables
// (sec 4) kernels
// (sec n) return
}
private:
// private variables
// private function(s)
helper() { ... }
dfs() { ... }
};Example (873. Length of Longest Fibonacci Subsequence):
-
code:
class Solution { public: int lenLongestFibSubseq(vector<int>& A) { const int n = A.size(); int ans = 0; vector<vector<int>> dp(n, vector<int>(n, 2)); unordered_map<int, int> numToIndex; for (int i = 0; i < n; ++i) numToIndex[A[i]] = i; for (int j = 0; j < n; ++j) for (int k = j + 1; k < n; ++k) { const int ai = A[k] - A[j]; if (ai < A[j] && numToIndex.count(ai)) { const int i = numToIndex[ai]; dp[j][k] = dp[i][j] + 1; ans = max(ans, dp[j][k]); } } return ans; } };
-
code (explanation):
class Solution { public: int lenLongestFibSubseq(vector<int>& A) { // Only get the value of size or length // when we use it twice or more times. // Add `const`, and separate this line from next section a blank line. const int n = A.size(); // Declare the variables in the proper scope as slow as possible. // Declare `ans` as soon as possible. // Order: ans -> dp -> STL -> pointers (TBD) int ans = 0; vector<vector<int>> dp(n, vector<int>(n, 2)); unordered_map<int, int> numToIndex; for (int i = 0; i < n; ++i) numToIndex[A[i]] = i; for (int j = 0; j < n; ++j) for (int k = j + 1; k < n; ++k) { const int ai = A[k] - A[j]; // use const if (ai < A[j] && numToIndex.count(ai)) { const int i = numToIndex[ai]; // use const dp[j][k] = dp[i][j] + 1; ans = max(ans, dp[j][k]); } } return ans; } };
// Linked-List
if (l1 || l2) { ... }
if (!l1 || !l2) { ... }
// String
if (str.empty()) { ... }
if (str.length() <= 2) { ... }
// Vector
if (vec.size() <= 2) { ... }return ans;
return {};// C++
unordered_set<string> seen;
unordered_map<char, int> count; // numToIndex, prefixToIndex
vector<int> count; // sometimes it's a better choice than `unordered_map`
stack<char> stack;
queue<TreeNode*> q;
deque<TreeNode*> deque;
auto compare = [](const ListNode* a, const ListNode* b) {
return a->val > b->val;
};
priority_queue<ListNode*, vector<ListNode*>, decltype(compare)> pq(compare);// Java
Set<String> seen = new HashSet<>();
Map<Character, Integer> count = new HashMap<>();
int[] count = new int[n];
Stack<Character> stack = new Stack<>();
Queue<Integer> q = new LinkedList<>();
Deque<Integer> deque = new ArrayDeque<>();
Queue<ListNode> pq = new PriorityQueue<>((a, b) -> a.val - b.val);# Python
seen = set() # or wordSet = set() if you like
count = {}
count = collections.defaultdict(int)
count = collections.defaultdict(list)
count = collections.Counter()
q = collections.deque([root])
deque = collections.deque([root])
stack = []- Always prefer to one character to represent index variables.
- Use
i,j,kin the loop, in that order.
int i = 0;
for (const int num : nums) { ... }for (int i = 0, j = 0; i < n; ++i) { ... }int k = 0;
for (int i = 0; i < n; ++i)
for (int j = i; j < n; ++j) { ... }int l = 0;
int r = nums.size() - 1;- Always prefer to one character to represent index variables.
- Always prefer to use
[l, r)pattern.
int l = 0;
int r = nums.size(); // or nums.size() - 1
while (l < r) {
const int m = l + (r - l) / 2;
if (f(m)) return m; // optional
if (g(m))
l = m + 1; // new range [m + 1, r)
else
r = m; // new range [l, m)
}
return l; // nums[l]ListNode dummy(0); // allocated on stack instead of heap
ListNode* curr;
ListNode* prev;
ListNode* next;
ListNode* slow;
ListNode* fast;
ListNode* head;
ListNode* tail;
ListNode* l1;
ListNode* l2;// 2D Vector
const int m = matrix.size();
const int n = matrix[0].size();
// if there're two strings
const int m = str1.length();
const int n = str2.length();
// if there's only a string
const int n = str.length();// vector<int> nums;
for (int i = 0; i < nums.size(); ++i) { ... }
for (const int num : nums) { ... }
// vector<string> words;
for (const string& word : words) { ... }
// string str;
for (int i = 0; i < str.length(); ++i) { ... }
for (const char c : str) { ... }
// unordered_set<int> set;
for (const int num : set) { ... }
// structured binding
// unordered_map<char, int> map;
for (const auto& [key, value] : map) { ... }
// ListNode* head;
for (ListNode* curr = head; curr; curr = curr->next) { ... }-
Always prefer to use
str.length()overstr.size(). -
Always use camelCase nomenclature when not listed above.
// C++ int currNum; int maxProfit; TreeNode* currNode;
-
When there's confliction in expression and function or reserved key word:
// C++ mini, std::min() maxi, std::max()# Python mini, min maxi, max summ, sum
-
When there are two maps/stacks, use meaningful names.
// C++ unordered_map<char, int> countA; unordered_map<char, int> countB;
-
When we need to count something, use
sum,countandtotal, in that order. -
Initialize vector with
0orfalseimplicitly. (TBD) -
constexpris used if possible. -
constis used if we get value ofsize()orlength(). -
const autois used when we iterate through amap -
Use
&whenever possible exceptintandcharbecause reference typically takes 4 bytes, whileinttakes 2/4 bytes andchartakes 1 byte -
Prefer to name variables in a "adjactive + noun" order. For example,
maxLeftis better thanleftMax.