We cannot directly compare the float value, like using the logic “==” symbol. But we can use: the way that using the division method to compare the result with a very small value.
1 | # float_num == cannot be used into the float number comparision. |
1 | Convert a number into the inverse number: |
1 | num = 150 |
1 | # here is the standard way |
Google Codestyle Pygide
In python we can use range() or just for loops to loop the elements from a list, but we still strongly suggest we use the enumerate, since it looks more python.
1 | for (index, num) in enumerate(nums): |
Reverse the list!!! Using range()
1 | for i in range(len(nums) - 1, -1, -1): |
While loop is just equal to the for loop in many ways:
1 | i = 0 |
1 | Input = '[1, 2, 3, 4]' |
1 | def swapInteger(swapList, swapIdx1, swapIdx2): |
In python the “self.” all can represent the inner nature of a function.
1 | class Student(): # Class name should follow the camel way |
init is the default construnction function that will run when you create that class. This is the compulsory element of the class.
Self it is the object itself, when we define the class we must declare it, but when we call it we will not see.
Instance is just object.
1 | student = Student('Jack', 90) |
We need to have the existence judge before we really run the function:
It can combine two cases: 1) End Case 2) Base Case.
1 | # here is the base case |
1 | list = list_1 + list_2 |
1 | list = list * 3 |
iteration
1 | for x in list_a: |
index id
1 | list_a[n] |
slice
1 | list_a[:] |
in
1 | 2 in list_a |
index method
1 | list_a.index("the value you want to search") |
count
1 | list.count(2) |
update through the index
1 | list_a[2] = ... |
Update through slicing
1 | list_b[:n] = [,,,] |
append
1 | list.append("will add an element from the end of the list") |
insert
1 | list.insert(index, "the element you want to insert") |
extend
1 | list_a = ["1", "2", "3"] |
This will enable us to insert the values before the list we want to append. It looks like “+”, but for “+”, we need to generate a new list, but for this strategy, there is no need to do this.
1 | list_b = ["1", "2", "3", "a", "b", "c"] |
=
1 | list_b [:2] = [] |
pop
1 | list_b.pop(index) |
If there is no index, it will defaultly delete the final value.
remove
1 | list_b.remove(index_value) |
del
1 | del list_a[3] |
1 | if self.items: |
len
1 | len(list_a) |
sort
1 | list_a.sort() |
reverse
1 | list_a.reverse() |
reverse sort
1 | list_a.sort(reverse = True) |
1 | list_demo = [i for i in range(101) if i % 5 == 0] |
1 | # generate a multiple value list |
We only can read tuple cannot do the CUD there.
When we do the copy the value
+
1 | string_a = string_a + string_b |
1 | string_a = string_a * 3 |
for
1 | for c in string_a: |
find
1 | string_a.find("a") |
replace
1 | string_a.replace("h", "www") |
replace
1 | string_a.replace("h", " ") |
len
1 | len(string_a) |
format
1 | "I am {}".format("Xiao") |
str()
1 | str(100) |
format the elements of the list into the string value
1 | list_demo = ["xiao", "zhang"] |
reverse the string
1 | # using for loop but it is not suggested!!! |
Linked list is not in the Python default data type, so we have to self define it. The first node and its reference can represent the whole linked list, because you can find from one to infinity one by one.
1 | class ListNode: |
while loop to read through the linked list
1 | while cur is not None: |
The core idea is that if we can know the head of the linkedlist, then we can know the all linkedlist. So in most cases, we will only store the head of the linkedlist. We will make use of the head of the linkedlist, to do the CRUD for all the linkedList. And these are the core idea for the Linkedlist. We believe if we can know the head of the LinkedList, then we can know all the LinkedList.
So here, we will do the all the operations based on the manipulation of the head of the linkedlist.
add(location, val)
1 | # here we want to do the operation like: add(2, 2) |
Here are the actual code:
1 | # Case 1. Add the value in within the linkedlist, which means the location is > 0 |
1 | # Case 2. Add the value in the head, where the location is 0 |
get(location)
Here, we need to do get(2)
1 | def get(self, location): |
traverse()
1 | def traverse(self): |
is_empty()
Check whether it is an empty linkedlist:
1 | def is_empty(self): |
set(location, val)
The set() function is very similar to the get function, but the get() is only return the value instead of get change the value.
1 | def set(self, location, val): |
remove(location, val)
Remove() is very similar to the add() operations.
If we want to remove the node we want to remove, we should remove the node before that node.
1 | # Case 1. Remove the value in within the linkedlist, which means the location is > 0 |
Stack is LIFO(last in first out).
In python, we can use list as a stack. The last element of the list can be the top stack.
List can be a kind of stack but in a higher level, since we can do the CRUD in the place we want but stack cannot. We can use the stack to realize the stack functions.
push(val)
1 | class MyStack: |
peek(): return the top stack value which is the last value in the list.
1 | class MyStack: |
pop()
It will only delete the element at the top of the stack.
1 | class MyStack: |
Queue is first in first out (FIFO). We can use the LinkedList to make this work. The reason that we are using the linked list instead of list is that: if we are using the list, for the head of that list, if we want to delete that node, the time complexity is o(n).
enqueue(val)
Get the value into the quene.
dequeue()
remove from the queue.
size()
check the elements number within the quene.
is_empty:
Check whether the quene is empty.
The binary tree only accepts the two child node for each parent node. If there is no specification, we will think that the tree is the binary tree. Binary tree is just like linked list, it is very important data structures. And there is also some therorums, that each tree can be converted into the many binary trees.
We can create a binary tree in this way:
We need to define the class of the tree:
1 | class TreeNode: |
Now, its time to build a binary tree:
1 | def build_tree(): |
This pic shows we already defined those nodes.
1 | node_1.left = node_2 |
We can read that data structure by traverse all the binary tree data.
Pre-order ( root - left - right)
The logic in here is that: for each node, we firstly find the root node, then the left-sub tree, finally the right-sub tree. We call this pre-order traverse.
Now we only knew the root node, we can print the whole tree by the root node. We can print the left-sub tree, and then the right-sub tree. In this way, we can print all the trees at the same time.
1 | def traverse_tree(root): |
The inorder way is: left-root-right, the postorder is left-right-root.
1 | def inorder_traverse(root): |
1 | def postorder_traverse(root): |
It will traverse all the tree level by level. For BFS, we will use the queue as basic data structures.
1 | from queue import Queue |
Recursion is just a way that how we write the algorithm. Recursive is a very smart way to do the algorithm, but recursive is not compulsory. Recursive is just a way that we do the programming, any recursive problem can be divided into the non-recursive problem.
There are three important factors that we need the recursive:
We need to know if this problem can be elegantly used the recursive way to solve.
We should know when the recursion will be stopped.
If the recursion is not stopped, how we divide the problems?
Eg: Fibonacci,
1 | 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ... |
The question is that if I gave you a number that in the Fibonacci, you should return the order value of that nth value.
1 | # The definition of the recursion: F(n) = F(n-1) + F(n-2) |
Algorithm is the way how we do things, the data structure is is the structure of how we storage the data.
二分法
二叉树/链表
递归/DFS
BFS/拓扑排序
哈希表
双指针
动态规划
堆
Time complexity expresses the efficiency of that algorithm’s efficiency.
Dynamic Programming
Linked List
Recursion
Binary Tree
Binary Search
Depth First Search (DFS)
There are three kinds of two pointers:
From the two sides to compare.
1 | class Solution: |
Here is the general answer, add the max value and the min value,
if > target, we just remove the max value,
if < target, we just remove the min value,
if = target, we just return true.
if we cannot even find any answer, return [-1, -1]
1 | class Solution: |
1 | class Solution: |
If we want to return the index of the values, so we have better to use the hash map.
1 | class Solution: |
There has a sequence like
Pivot:
L > Pivot && R < Pivot => swap L and R
L <= Pivot => L = L + 1
R >= Pivot => R = R - 1
L > R => swap L and R
1 | R Pivot L |
1 | L Pivot |
1 | Pivot R |
1 | R L Pivot |
1 | def quick_sort(sequence): |
1 | def quicksort(xs): |
1 | def quickSort(array): |
1 | Given [3, 2, 1, 4, 5], return [1, 2, 3, 4, 5] |
Binary search is mostly used for search one target value from a sorted array. Binary search used some “decrease and conquer” algorithmic paradigm, which is not include “divide and conquer” algorithm.
The difference between the “permutation” and “combination” is that, for the processed data the combination is without any order!!!
Eg. from 5 numbers we just choose 3, unordered, then we call it combination:
Like (1, 2, 3) and (2, 1, 3) and (3, 1, 2) they are just the same.
The idea of the binary search is to keep the half of the “useful” data, and throw the “useless” part.
Template:
1 | start + 1 < end |
Find any position of a target number in a sorted array. Return -1
if target does not exist.
1 | Input: nums = [1,2,2,4,5,5], target = 2 |
1 | def binarySearch(nums, target): |
Find the sum of from the 1~100
BFS (Broad First Search) focuses on the width of the search.
DFS (Deep First Search) focuses on the depth of the search.
1 | sum = 0 |
After we use the recursion, f(1) = 1, f(n) = f(n-1) + n
1: f(1) = 1
2: f(2) = f(1) + 1
If we want to prove f(n), we need firstly prove f(1) is valid, and the next step is just to make a hypothesis that the f(n-1) is also valid. So from f(n-1) we can prove the f(n) is valid.
1 | def recursive_sum(n): |
1 | if n = 5: |
Letter Combinations of a Phone Number:https://leetcode.com/problems/letter-combinations-of-a-phone-number/
1 | Example 1: |
1 | KEYBOARD = { |
1 | # when we do the recursion, the first step is to build a variable, here we defined a dict, which shows the mapping structure. We do not use the "0" and "1". Actually in python, the dict can be thought as the hashmap. |
1 | combinationsHere are just a example of how the dfs works: |
1 | class Solution(object): |
1 | source = "abcdefg" |
Much better solution:
1 | source = "abcdefg" |
No many loops, no more than 3 levels:
Always ask if there is the code review part
Improvements:
**A good readable code is the most important part of the coding part, since nobody want to maintain an unreadable code there! **
1 | if (grid[i][j]) == 1) { |
Needs to explain what is Magic number: 1 & 2! There is a good way to write it shows the industrial experience:
1 | class GridType: |
1 | list[i] |
Always decouple the codes and decrease the readability difficulty, system is much important than details. So if we use smaller modules rather than big chunks of code, that is very important. If there is an error, so it will only affect that single module instead of others.
Good naming functions:
1 | find_name_by_... |
Good codes do not need comments, but you can read easily from the name of the function, logic of the functions… Trash codes need comments…
Judge ways:
1 | Logicality |
Always code before ask the requirements, when totally understood, just stop chatting and write codes. Do not need to ask a lot when do the codings there. In order to save time.
If the question you already met, then you should tell the people, so he can change the question.
Introspective task: Ask a question, and answer what they feel about the question.
Triangulation: use multiple methods to do the research.
Paradigm: A typical example of a phenomenon.
Action research: Know the effective of a devices, tested by a bunch of users
Deliberate actions: Give the candy, read a book. Intions to let someone do something.
Uncontrived: Not artifical
Maintainning relationships and trust participants: Will you keep the codes/data in your own computer?