Add binaryheap, circularqueue, linkedlist, maxxor, union find set

This commit is contained in:
mbinary 2018-12-29 19:30:21 +08:00
parent 273702e4e4
commit b6805c66ce
33 changed files with 630 additions and 54 deletions

View File

@ -2,16 +2,12 @@
# Algorithm
>Notes and codes for learning algorithm and data structures :smiley:
Some pictures and ideas are from `<<Introduction to Algotithm>>
Some pictures and ideas are from `<<Introduction to Algotithm>>`
I use python 3.6+ and c++ to implements them.
Since I used f-Strings in python, you may use python 3.6+ to run the following python scripts.
>>I am still learning new things and this repo is always updating.
I use python 3.6+ and c/c++ to implement them.
# Notice
Currently, Github can't render latex math formulas.
So,if you wannt to view the notes which contain latex math formulas and are in markdown format, you can visit [my blog](https://mbinary.coding.me)
Currently, Github can't render latex math formulas.Thus,if you want to view the markodwn notes which contain latex math formulas, you can visit [my blog](https://mbinary.coding.me)
# Index
* [.](.)
@ -21,12 +17,15 @@ So,if you wannt to view the notes which contain latex math formulas and are in m
* [allOone](./dataStructure/allOone)
* [bTree.py](./dataStructure/bTree.py)
* [binaryHeap.py](./dataStructure/binaryHeap.py)
* [binaryHeap1.py](./dataStructure/binaryHeap1.py)
* [binaryTree.py](./dataStructure/binaryTree.py)
* [circularQueue.py](./dataStructure/circularQueue.py)
* [graph](./dataStructure/graph)
* [hashTable.py](./dataStructure/hashTable.py)
* [huffman](./dataStructure/huffman)
* [intervalTree.py](./dataStructure/intervalTree.py)
* [leftHeap.py](./dataStructure/leftHeap.py)
* [linkedList.py](./dataStructure/linkedList.py)
* [loserTree.py](./dataStructure/loserTree.py)
* [map.cc](./dataStructure/map.cc)
* [polynomial.cpp](./dataStructure/polynomial.cpp)
@ -35,6 +34,7 @@ So,if you wannt to view the notes which contain latex math formulas and are in m
* [redBlackTree0.py](./dataStructure/redBlackTree0.py)
* [splayTree.py](./dataStructure/splayTree.py)
* [trie](./dataStructure/trie)
* [unionFindSet](./dataStructure/unionFindSet)
* [winnerTree.py](./dataStructure/winnerTree.py)
* [divideAndConquer](./divideAndConquer)
* [min_distance_of_n_points.py](./divideAndConquer/min_distance_of_n_points.py)
@ -59,29 +59,15 @@ So,if you wannt to view the notes which contain latex math formulas and are in m
* [stoneGame.py](./dynamicProgramming/stoneGame.py)
* [testVec2d.hs](./dynamicProgramming/testVec2d.hs)
* [wildcard_matching.py](./dynamicProgramming/wildcard_matching.py)
* [graph](./graph)
* [isBipartGraph.py](./graph/isBipartGraph.py)
* [math](./math)
* [README.md](./math/README.md)
* [euler.py](./math/euler.py)
* [factor.py](./math/factor.py)
* [gcd.py](./math/gcd.py)
* [isPrime.py](./math/isPrime.py)
* [modulo_equation.py](./math/modulo_equation.py)
* [num_weight.py](./math/num_weight.py)
* [permute_back_track.py](./math/permute_back_track.py)
* [permute_cantor.c](./math/permute_cantor.c)
* [permute_divide_and_conquer.py](./math/permute_divide_and_conquer.py)
* [permute_next_arrangement.c](./math/permute_next_arrangement.c)
* [primesLEn.hs](./math/primesLEn.hs)
* [numericalAnalysis](./numericalAnalysis)
* [README.md](./numericalAnalysis/README.md)
* [interplotion.py](./numericalAnalysis/interplotion.py)
* [iteration.py](./numericalAnalysis/iteration.py)
* [least_square.py](./numericalAnalysis/least_square.py)
* [linear_equation.py](./numericalAnalysis/linear_equation.py)
* [numerical_differential.py](./numericalAnalysis/numerical_differential.py)
* [numerical_integration.py](./numericalAnalysis/numerical_integration.py)
* [solve-linear-by-iteration.py](./numericalAnalysis/solve-linear-by-iteration.py)
* [vector_norm.py](./numericalAnalysis/vector_norm.py)
* [convertWeight.py](./math/convertWeight.py)
* [fastPow.py](./math/fastPow.py)
* [numberTheory](./math/numberTheory)
* [numericalAnalysis](./math/numericalAnalysis)
* [permute](./math/permute)
* [search](./search)
* [8Astar.py](./search/8Astar.py)
* [BFS_knight.hs](./search/BFS_knight.hs)
@ -91,6 +77,7 @@ So,if you wannt to view the notes which contain latex math formulas and are in m
* [sort](./sort)
* [binaryTree.py](./sort/binaryTree.py)
* [heapSort.py](./sort/heapSort.py)
* [quickSort.c](./sort/quickSort.c)
* [quickSort.py](./sort/quickSort.py)
* [radixSort.py](./sort/radixSort.py)
* [select.py](./sort/select.py)

View File

@ -0,0 +1,72 @@
from functools import partial
class heap:
def __init__(self,lst,reverse = False):
self.data= heapify(lst,reverse)
self.cmp = partial(lambda i,j,r:cmp(self.data[i],self.data[j],r),r= reverse)
def getTop(self):
return self.data[0]
def __getitem__(self,idx):
return self.data[idx]
def __bool__(self):
return self.data != []
def popTop(self):
ret = self.data[0]
n = len(self.data)
cur = 1
while cur * 2<=n:
chd = cur-1
r_idx = cur*2
l_idx = r_idx-1
if r_idx==n:
self.data[chd] = self.data[l_idx]
break
j = l_idx if self.cmp(l_idx,r_idx)<0 else r_idx
self.data[chd] = self.data[j]
cur = j+1
self.data[cur-1] = self.data[-1]
self.data.pop()
return ret
def addNode(self,val):
self.data.append(val)
self.data = one_heapify(len(self.data)-1)
def cmp(n1,n2,reverse=False):
fac = -1 if reverse else 1
if n1 < n2: return -fac
elif n1 > n2: return fac
return 0
def heapify(lst,reverse = False):
for i in range(len(lst)):
lst = one_heapify(lst,i,reverse)
return lst
def one_heapify(lst,cur,reverse = False):
cur +=1
while cur>1:
chd = cur-1
prt = cur//2-1
if cmp(lst[prt],lst[chd],reverse)<0:
break
lst[prt],lst[chd] = lst[chd], lst[prt]
cur = prt+1
return lst
def heapSort(lst,reverse = False):
lst = lst.copy()
hp = heap(lst,reverse)
ret = []
while hp:
ret.append(hp.popTop())
return ret
if __name__ == '__main__':
from random import randint
n = randint(10,20)
lst = [randint(0,100) for i in range(n)]
print('random : ', lst)
print('small-heap: ', heapify(lst))
print('big-heap : ', heapify(lst,True))
print('ascend : ', heapSort(lst))
print('descend : ', heapSort(lst,True))

View File

@ -0,0 +1,76 @@
class MyCircularQueue:
def __init__(self, k):
"""
Initialize your data structure here. Set the size of the queue to be k.
:type k: int
"""
self.size = k+1
self.data = [0]*self.size
self.head = self.rear = 0
def enQueue(self, value):
"""
Insert an element into the circular queue. Return true if the operation is successful.
:type value: int
:rtype: bool
"""
if self.isFull():
return False
self.data[self.rear] = value
self.rear = (self.rear+1)%self.size
return True
def deQueue(self):
"""
Delete an element from the circular queue. Return true if the operation is successful.
:rtype: bool
"""
if self.isEmpty():
return False
self.head = (self.head+1)%self.size
return True
def Front(self):
"""
Get the front item from the queue.
:rtype: int
"""
if self.isEmpty():
return -1
return self.data[self.head]
def Rear(self):
"""
Get the last item from the queue.
:rtype: int
"""
if self.isEmpty():
return -1
return self.data[(self.rear-1)%self.size]
def isEmpty(self):
"""
Checks whether the circular queue is empty or not.
:rtype: bool
"""
return self.head ==self.rear
def isFull(self):
"""
Checks whether the circular queue is full or not.
:rtype: bool
"""
return (self.head - self.rear)%self.size ==1
# Your MyCircularQueue object will be instantiated and called as such:
# obj = MyCircularQueue(k)
# param_1 = obj.enQueue(value)
# param_2 = obj.deQueue()
# param_3 = obj.Front()
# param_4 = obj.Rear()
# param_5 = obj.isEmpty()
# param_6 = obj.isFull()

View File

@ -0,0 +1,84 @@
class node:
def __init__(self,val,follow=None):
self.val = val
self.follow = follow
class MyLinkedList:
def __init__(self):
"""
Initialize your data structure here.
"""
self.tail = self.head = node(None)
def get(self, index):
"""
Get the value of the index-th node in the linked list. If the index is invalid, return -1.
:type index: int
:rtype: int
"""
nd = self.head
for i in range(index+1):
nd = nd.follow
if nd is None:return -1
return nd.val
def addAtHead(self, val):
"""
Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list.
:type val: int
:rtype: void
"""
nd = node(val,self.head.follow)
self.head .follow = nd
if self.tail.val is None:self.tail = nd
def addAtTail(self, val):
"""
Append a node of value val to the last element of the linked list.
:type val: int
:rtype: void
"""
self.tail.follow = node(val)
self.tail = self.tail.follow
def addAtIndex(self, index, val):
"""
Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted.
:type index: int
:type val: int
:rtype: void
"""
nd = self.head
for i in range(index):
nd = nd.follow
if nd is None:
return
new = node(val,nd.follow)
nd.follow = new
if self.tail == nd:
self.tail = new
def deleteAtIndex(self, index):
"""
Delete the index-th node in the linked list, if the index is valid.
:type index: int
:rtype: void
"""
nd = self.head
for i in range(index):
nd = nd.follow
if nd is None:return
if self.tail == nd.follow:self.tail = nd
if nd.follow:nd.follow = nd.follow.follow
# Your MyLinkedList object will be instantiated and called as such:
# obj = MyLinkedList()
# param_1 = obj.get(index)
# obj.addAtHead(val)
# obj.addAtTail(val)
# obj.addAtIndex(index,val)
# obj.deleteAtIndex(index)

View File

@ -61,7 +61,6 @@ class MapSum:
nd[i] = node(i)
nd = nd[i]
nd.n = val
def visit(self,nd):
ret = nd.n
for chd in nd:

View File

@ -0,0 +1,70 @@
#coding: utf-8
''' mbinary
#######################################################################
# File : maxXor.py
# Author: mbinary
# Mail: zhuheqin1@gmail.com
# Blog: https://mbinary.coding.me
# Github: https://github.com/mbinary
# Created Time: 2018-12-22 09:51
# Description:
maximum_xor_of_two_numbers_in_an_array:
using trie data structure
O(k*n) where n=length(array),k is the max length of radix of num
#######################################################################
'''
class node:
def __init__(self,key,hasKey = False):
self.key = key
self.hasKey = hasKey
self.children={}
def __getitem__(self,key):
return self.children[key]
def __len__(self):
return len(self.children)
def __setitem__(self,key,val):
self.children[key]=val
def __contains__(self,key):
return key in self.children
class trie:
def __init__(self,maxDepth=32):
self.root=node(None)
self.maxDepth = maxDepth
def add(self,num):
nd = self.root
s = bin(num)[2:].rjust(self.maxDepth,'0')
for n in s:
if n not in nd:
nd[n]=node(n)
nd=nd[n]
def search(self,num):
ret = 0
nd = self.root
s = bin(num)[2:].rjust(self.maxDepth,'0')
for n in s:
# note that it's the flip bit
flip = '1' if n=='0' else '0'
if flip in nd:
ret=ret*2+1
nd=nd[flip]
else:
ret*=2
nd=nd[n]
return ret
def findMaximumXOR(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if not nums:return 0
n = len(bin(max(nums)))-1
t = trie(n)
for i in nums:t.add(i)
return max(t.search(i) for i in nums)
if __name__=='__main__':
from random import randint
nums = [randint(1,int(1e18)) for i in 100]
findMaximumXOR(nums)

View File

@ -0,0 +1,99 @@
#coding: utf-8
''' mbinary
#######################################################################
# File : accountsMerge.py
# Author: mbinary
# Mail: zhuheqin1@gmail.com
# Blog: https://mbinary.coding.me
# Github: https://github.com/mbinary
# Created Time: 2018-12-18 17:07
# Description:
给定一个列表 accounts每个元素 accounts[i] 是一个字符串列表其中第一个元素 accounts[i][0] 名称 (name)其余元素是 emails 表示该帐户的邮箱地址
现在我们想合并这些帐户如果两个帐户都有一些共同的邮件地址则两个帐户必定属于同一个人请注意即使两个帐户具有相同的名称它们也可能属于不同的人因为人们可能具有相同的名称一个人最初可以拥有任意数量的帐户但其所有帐户都具有相同的名称
合并帐户后按以下格式返回帐户每个帐户的第一个元素是名称其余元素是按顺序排列的邮箱地址accounts 本身可以以任意顺序返回
例子 1:
Input:
accounts = [["John", "johnsmith@mail.com", "john00@mail.com"], ["John", "johnnybravo@mail.com"], ["John", "johnsmith@mail.com", "john_newyork@mail.com"], ["Mary", "mary@mail.com"]]
Output: [["John", 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com'], ["John", "johnnybravo@mail.com"], ["Mary", "mary@mail.com"]]
Explanation:
第一个和第三个 John 是同一个人因为他们有共同的电子邮件 "johnsmith@mail.com"
第二个 John Mary 是不同的人因为他们的电子邮件地址没有被其他帐户使用
#######################################################################
'''
class Solution(object):
def accountsMerge(self, accounts):
"""
:type accounts: List[List[str]]
:rtype: List[List[str]]
"""
mailDic = {}
for ct,i in enumerate(accounts):
for j in i[1:]:
mailDic[j] = (ct,i[0])
mails = {mail:idx for idx,mail in enumerate(mailDic.keys())}
mailNum = len(mails)
self.findSet = [i for i in range(mailNum)]
for li in accounts:
n = len(li)
for i in range(1,n-1):
for j in range(i+1,n):
self.union(mails[li[i]],mails[li[j]])
dic = {}
mails = {j:i for i,j in mails.items()}
for i in range(mailNum):
mail = mails[i]
n = mailDic[mails[self.find(i)]][0]
if n in dic:
dic[n].append(mail)
else:
dic[n] = [mail]
nameId = {i[0]:i[1] for i in mailDic.values()}
return [[nameId[i]]+sorted(mail) for i,mail in dic.items()]
def find(self,i):
if self.findSet[i]!=i:
n = self.find(self.findSet[i])
self.findSet[i] = n
return self.findSet[i]
def union(self,i,j):
if i!=j:
n = self.find(i)
if n!=self.find(j):
self.findSet[n] = self.findSet[j]
class Solution2:
'''并查映射'''
def accountsMerge(self, accounts):
"""
:type accounts: List[List[str]]
:rtype: List[List[str]]
"""
mailDic = {j:ct for ct,i in enumerate(accounts) for j in i[1:]}
self.findSet = {i:i for i in mailDic}
for li in accounts:
n = len(li)
for i in range(1,n-1):
for j in range(i+1,n):
self.union(li[i],li[j])
dic = {}
for mail in self.findSet:
n = mailDic[self.find(mail)]
if n in dic:
dic[n].append(mail)
else:
dic[n] = [mail]
return [[accounts[i][0]]+sorted(mail) for i,mail in dic.items()]
def find(self,i):
if self.findSet[i]!=i:
n = self.find(self.findSet[i])
self.findSet[i] = n
return self.findSet[i]
def union(self,i,j):
if i!=j:
n = self.find(i)
if n!=self.find(j):
self.findSet[n] = self.findSet[j]

View File

@ -0,0 +1,42 @@
#coding: utf-8
''' mbinary
#######################################################################
# File : unionFind.py
# Author: mbinary
# Mail: zhuheqin1@gmail.com
# Blog: https://mbinary.coding.me
# Github: https://github.com/mbinary
# Created Time: 2018-12-18 14:53
# Description:
班上有 N 名学生其中有些人是朋友有些则不是他们的友谊具有是传递性如果已知 A B 的朋友B C 的朋友那么我们可以认为 A 也是 C 的朋友所谓的朋友圈是指所有朋友的集合
给定一个 N * N 的矩阵 M表示班级中学生之间的朋友关系如果 M[i][j] = 1表示已知第 i 个和 j 个学生互为朋友关系否则为不知道你必须输出所有学生中的已知的朋友圈总数
#######################################################################
'''
class Solution(object):
def findCircleNum(self, M):
"""
:type M: List[List[int]]
:rtype: int
"""
n = len(M)
self.data = [i for i in range(n)]
for i in range(n):
for j in range(n):
if M[i][j]==1:
self.union(i,j)
ret = set()
for i in range(n):
ret.add(self.find(i))
return len(ret)
def find(self,i):
if self.data[i]!=i:
self.data[i] = self.find(self.data[i])
return self.data[i]
def union(self,i,j):
if i!=j:
n = self.find(i)
if n!=self.find(j):
self.data[n]= self.data[j]

30
graph/isBipartGraph.py Normal file
View File

@ -0,0 +1,30 @@
#coding: utf-8
''' mbinary
#######################################################################
# File : isBipartGraph.py
# Author: mbinary
# Mail: zhuheqin1@gmail.com
# Blog: https://mbinary.coding.me
# Github: https://github.com/mbinary
# Created Time: 2018-12-21 15:00
# Description: Judge if a graph is bipartite
The theorical idea is to judge whether the graph has a odd-path circle. However, it's hard to implement.
The following codes show a method that colors the nodes by dfs.
#######################################################################
'''
def isBipartite(self, graph):
"""
:type graph: List[List[int]]
:rtype: bool
"""
n = len(graph)
self.node = graph
self.color = {i:None for i in range(n)}
return all(self.dfs(i,True) for i in range(n) if self.color[i] is None)
def dfs(self,n,col=True):
if self.color[n] is None:
self.color[n]=col
return all(self.dfs(i,not col) for i in self.node[n])
else:return col==self.color[n]

31
math/fastPow.py Normal file
View File

@ -0,0 +1,31 @@
#coding: utf-8
''' mbinary
#######################################################################
# File : fastPow.py
# Author: mbinary
# Mail: zhuheqin1@gmail.com
# Blog: https://mbinary.coding.me
# Github: https://github.com/mbinary
# Created Time: 2018-12-17 21:39
# Description: fast power
#######################################################################
'''
def fastPow(a,n):
'''a^n'''
rst = 1
while n:
if n%2:
rst *=a
n>>=1
a*=a
return rst
def fastMul(a,b):
'''a*b'''
rst = 0
while b:
if b&1:
rst +=a
b>>=1
a*=2

View File

@ -35,6 +35,16 @@ def factor(n):
cycle_size *=2
x_fixed = x
return factor(fact)+factor(n//fact)
def fact(n):
f=2
ret = []
while f*f<=n:
while not n%f:
ret.append(f)
n//f
f+=1
if n>1:ret.append(n)
return ret
if __name__=='__main__':

View File

@ -0,0 +1,60 @@
#coding: utf-8
''' mbinary
#######################################################################
# File : hammingDistance.py
# Author: mbinary
# Mail: zhuheqin1@gmail.com
# Blog: https://mbinary.coding.me
# Github: https://github.com/mbinary
# Created Time: 2018-12-17 17:36
# Description:
hamming distance is the number of different position (or binary bit for number) of two strings.
eg 'abac', 'ab': 2 1010,11 : 3
#######################################################################
'''
def hammingDistance(a,b):
if isinstance(a,int):
n = a^b
ct = 0
while n:
ct+=n%2
n>>=1
return ct
else:
n,m = len(a),len(b)
ret = 0
for i,j in zip(a,b):
ret+= i==j
return ret+abs(n-m)
def totalHammingDistance(lst):
'''return sum of any two items(num or lst( str)) in lst'''
length = len(lst)
if length ==0:return 0
if isinstance(lst[0],int):
bits = [0] * len(bin(max(lst)))
for n in lst:
ct = 0
while n:
if n%2==1:
bits[ct]+=1
ct+=1
n>>=1
return sum(i*(length-i) for i in bits)
else:
mx = len(max(lst,key=len))
position = [dict() for i in range(mx)]
for li in lst:
for i,x in enumerate(li):
if x in position[i]:
position[i][x] +=1
else:
position[i][x] =1
ret = 0
for dic in position:
left = length
for i in dic.values():
ret+=i*(left-i) # key step
left -=i # key step
return ret

View File

@ -1,12 +1,13 @@
/* mbinary
#########################################################################
# File : permute_next_arrangement.c
# File : permute_next_permutation.c
# Author: mbinary
# Mail: zhuheqin1@gmail.com
# Blog: https://mbinary.coding.me
# Github: https://github.com/mbinary
# Created Time: 2018-11-17 14:31
# Description:
# Description: support duplicate values.
eg [1,1,5] nextPermutation [1,5,1]
#########################################################################
*/
#include<stdio.h>
@ -18,29 +19,28 @@ void swap(int*arr,int i,int j)
arr[i] = arr[j];
arr[j] = tmp;
}
void nextArrangement(int *arr,int n)
void reverse(int *arr,int i,int j)
{
if(arr[n-1]>arr[n-2]){
swap(arr,n-1,n-2);
}else{
while (i<j)swap(arr,i++,j--);
}
void nextPermutation(int *arr,int n)
{
if(n>1){
int i;
for(i=n-1;i>0;--i){
if(arr[i]>arr[i-1])break;
}
if(i==0){//reverse arrangement, n,n-1,...,1
for(;i<n;++i)arr[i] = i;
return ;
}
i=i-1;
i-=1;
if(i>=0){
for(int j=n-1;j>i;j--){
if(arr[j]>arr[i]){
int tmp = arr[j];
for(int k = j;k>i;--k)arr[k] = arr[k-1];
arr[i] =tmp;
swap(arr,j,i);
break;
}
}
}
reverse(arr,i+1,n-1);
}
}
void printArr(int *arr,int n)
@ -58,6 +58,6 @@ int main()
for(int i=0;i<fac;++i){
printf("rank %d :",i);
printArr(a,n);
nextArrangement(a,n);
nextPermutation(a,n);
}
}

20
sort/quickSort.c Normal file
View File

@ -0,0 +1,20 @@
int partition(int *arr,int i,int j)
{
int pivot = arr[j],p=i,q=j;
while(p<q){
while(p<q && arr[p]<=pivot)++p;
if(p<q)arr[q--]=arr[p];
while(p<q && arr[q]>pivot)--q;
if(p<q)arr[p++]=arr[q];
}
arr[p]=pivot;
return p;
}
void quickSort(int *arr,int i,int j)
{
if(i<j){
int p = partition(arr,i,j);
quickSort(arr,i,p-1);
quickSort(arr,p+1,j);
}
}

View File

@ -2,16 +2,12 @@ README = r'''
# Algorithm
>Notes and codes for learning algorithm and data structures :smiley:
Some pictures and ideas are from `<<Introduction to Algotithm>>
Some pictures and ideas are from `<<Introduction to Algotithm>>`
I use python 3.6+ and c++ to implements them.
Since I used f-Strings in python, you may use python 3.6+ to run the following python scripts.
>>I am still learning new things and this repo is always updating.
I use python 3.6+ and c/c++ to implement them.
# Notice
Currently, Github can't render latex math formulas.
So,if you wannt to view the notes which contain latex math formulas and are in markdown format, you can visit [my blog](https://mbinary.coding.me)
Currently, Github can't render latex math formulas.Thus,if you want to view the markodwn notes which contain latex math formulas, you can visit [my blog](https://mbinary.coding.me)
# Index
{index}