contributed by < yaohwang99
>
In class note, Uduru0522 showed that it is more efficient to delete a node if we use indirect pointer pprev
.
Consider the version with the following data structure:
prev
of the first node is NULL
because it can only point to struct hlist_node
.prev
and next
points to struct hlist_node
.In the above version, traversing the nodes would be more efficient because it is a direct pointer. However, for a decent has table, collision rarely occurs so the linked list will not be long. Therefore, the advantage of deleting a node outweigh the disadvantage of traversing the nodes.
map_add()
Above graph is initial state
*returnSize
to 0 and space for 2 integer.nums
does not have an answer, returnSize will still be 0 and return ret
, implying that *ret
contains garbage value.nums
, use targer - nums[i]
as key to find the index of the corresponding number.nums[i]
and current index i
to map, continue to next element of nums
.In map_deinit(), I don't understand why n->pprev
can be NULL.
cy023
pointed out that it can pass leetcode test even if it is commented.
hash.h
Note:
Initialize hash using designated initializer.
Hash function:
Linux kernel will check the word size of the machine and use the corresponding hash function.
If key is 64 bits, use hash_long(), if key is 32 bits, use hash_32().
If word size is 32 bits, hash_long() is hash_32(), if word size is 64 bits, hash_long() is hash_64()
If word size is 32 bits but wants to use hash_64(),hash_32((u32)val ^ __hash_32(val >> 32), bits)
produces the same result.
The hash function val * GOLDEN_RATIO_32 >> (32 - bits)
uses the first bits
number of bits of val * GOLDEN_RATIO_32
as bucket index.
For example, bits = 3, val = 5, then val * GOLDEN_RATIO_32
== 0xE8EA9F63 (discard overflowed bits), bucket index = 0xE.
head->val
equals head->next->value
, move head
to next node until the statement is false or end of the list.head->next
as new head of the sublist, repeat the algorithm.In the sample code, the removed node is not freed and is not pointed by any pointer.
Create struct ListNode *removeSublist(struct ListNode *head)
which removes all the repeated value until the first non-repeated node.
For example, the following list
becomes:
after calling struct ListNode *removeSublist(struct ListNode *head)
.
Using struct ListNode *removeSublist(struct ListNode *head)
, implement the algorithm by iteration.
head
to the first non-repeated node by calling removeSublist()
.prev
initialized to head
head
.head->prev->next=NULL
deleteDuplicates()
, which could be either the recursive or the iterative version.prev
pointer in each node, set next
of last node to head to convert back to circular list.dhead
and hlink
forms a list by every node in cache. dhead is the head and the tail is the least recently used node.hhead[]
is each bucket of the hash table, each bucket points to nodes connected by hlink
.capacity
is the max number of node the cache can contain. count
records current number of nodes in the cache.obj
pointer to newly allocated memory.obj
.When allocating memory, sizeof(*obj)
is equaled to 2*sizeof(int)+sizeof(struct list_head)
.
Because dhead
list contains every node, we can iterate through it and delete (remove and then free) each node.
We need to delete the current node in each iteration, so we need the safe
pointer to the next entry.
MMM1: list_for_each_entry_safe
dhead
list (most recently used) and return the value.-1
.MMM2: list_for_each_entry
Similar to lRUCacheGet
.
dhead
list (most recently used) and set the value in the node to input value.dhead
list (least recently used).key
and value
to cache.MMM3: list_for_each_entry
MMM4: list_last_entry
Add the following code at the top of the script.
lru_cache.h
I only understood a little.
lru_cache:
lru
: pointer to list of unused but ready to be reused or recycled element, the least recently used item is kept at lru->prev
free
: pointer to list of unused and ready to be recycled element
in_use
: pointer to list of element in use
to_be_changed
: pointer to
lc_cache
: pointer to struct kmem_cache
element_size
: size of tracked objects
element_off
: offset of struct lc_element
member in the tracked object
nr_elements
: number of elements (indices)
max_pending_changes
: allow to accumulate number of changes
pending_changes
: number of elements currently on to_be_changed list
used
: number of elements currently on in_use list
hits, misses, starving, locked, changed
:number of elements
flags
: flag bits (enum) for lru_cache
lc_private
:
name
:
lc_slot
:nr_elements
there
lc_element
:nr_elements
there
lc_find
: find which lc_slot
bucket the element is in using lc_new_number
as key.
lc_get()
:
lc_find()
.hits
and other statistics then move the element to in_use
list.miss
.lc_set()
: associate index with label, move element to lru
list or free
list.
lc_put()
: decrease refcnt
, if refcnt == 0
, move element to lru
list.
nums
and put each num in hash table.key-1
, if so, repeat for key-2
and so on until the key is not found, record how many are found.LLL: --left
key+1
, if so, repeat for key+2
and so on until the key is not found, record how many are found.RRR: --right
The above method takes because for each number we have to iterate again to know the length of each consecutive sequence
We can achieve if we record the consecutive sequence when inserting the number in the bucket.
Consider the following example:
If we insert 3, we need to updatemap[3]
, map[1]
and map[5]
and don't care about the other keys.
Because 1~5 is a known consecutive sequence, if 1~5 is inserted again, nothing will be changed.