"""
cell
ctrl+enter 运行当前的cell
shift+enter 运行当前cell并跳转到下一个cell 爬虫 web后台 数据分析 机器学习
dd:删除当前选中的cell
a:当前cell上方创建一个cell
b:当前cell下方创建一个cell
"""
1+2
3
s1=str()
s2="tanghaijun"
s2len=len(s2)
print(s2len)
s2[0:4]
s2[7:10]
s2[-3:]
s2[:5]
s3=s2[0:4]
display(s3)
s3+='jun'
display(s3)
s3list=list(s3)
display(s3list)
display(s2[4])
display(s2.index('i'))
display(s2.find('w'))
display(s2.find('i'))
10
'tang'
'tangjun'
['t', 'a', 'n', 'g', 'j', 'u', 'n']
'h'
6
-1
6
"""
Java版字符串操作
String s1 = new String();
String s2 = "billryan";
int s2Len = s2.length();
s2.substring(4, 8); // return "ryan"
StringBuilder s3 = new StringBuilder(s2.substring(4, 8));
s3.append("bill");
String s2New = s3.toString(); // return "ryanbill"
// convert String to char array
char[] s2Char = s2.toCharArray();
// char at index 4
char ch = s2.charAt(4); // return 'r'
// find index at first
int index = s2.indexOf('r'); // return 4. if not found, return -1
StringBuffer 与 StringBuilder, 前者保证线程安全,后者不是,但单线程下效率⾼⼀些,⼀般使⽤
StringBuilder
"""
"""
链表是一种最基本的,最简单的数据结构,元素之间的关系是一对一的关系,
除了第一个和最后一个元素之外,其他数据元素都是收尾相接,线性表有两种
存储方式,一种顺序存储结构,另外一种就是链式存储结构,常见的数组就是
顺序存储,集合就是链式存储
相反,链式存储结构就是两个相邻的元素在内存中可能不是相邻的,每⼀个元素都有⼀个指针域,指
针域⼀般是存储着到下⼀个元素的指针。这种存储⽅式的优点是定点插⼊和定点删除的时间复杂度为
O(1),不会浪费太多内存,添加元素的时候才会申请内存,删除元素会释放内存。缺点是访问的时间
复杂度最坏为 O(n)。
顺序表的特性是随机读取,也就是访问⼀个元素的时间复杂度是O(1),链式表的特性是插⼊和删除的
时间复杂度为O(1)。
链表就是链式存储的线性表。根据指针域的不同,链表分为单向链表、双向链表、循环链表等等。
"""
'\n 链表是一种最基本的,最简单的数据结构,元素之间的关系是一对一的关系,\n 除了第一个和最后一个元素之外,其他数据元素都是收尾相接,线性表有两种\n 存储方式,一种顺序存储结构,另外一种就是链式存储结构,常见的数组就是\n 顺序存储,集合就是链式存储\n'
"""
时间复杂度的阶有:
O(1):常量的时间阶
O(n):线性的时间阶
O(log n):对数的时间阶
O(nlogn):线性对数时间阶
O(n^k): k>=2 k次方的时间阶
"""
1+1
2+2
4+4
8
"""
算法中基本操作重复执行的次数是问题规模n的某个函数,其时间
度量记作T(n)=O(f(n))称作算法的渐进时间复杂度,简称时间复杂度
"""
for(i=1;i<=n;i++){
print(i)
}
File "", line 6
for(i=1;i<=n;i++){
^
SyntaxError: invalid syntax
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
print(c[i][j])
}
}
File "", line 2
for(i=1;i<=n;i++){
^
SyntaxError: invalid syntax
"""
空间复杂度:指算法编写成程序后,在计算机中运行时所需要存储
空间大小的度量,记作S(n)=O(f(n))
其中n为问题的规模(或者大小)
存储空间一般包含三个方面:
-指令常数变量所占用的存储空间
-输入数据所占用的存储空间
-辅助(存储空间)
一般的 算法的空间指的就是辅助空间
一维数组 a[n] 空间复杂度O(n)
二维数组 a[n][m] 空间复杂度O(n*m)
"""
class ListNode:
def __init__(self,val):
self.val=val;
self.next=None
"""
C++实现
struct ListNode {
int val;
ListNode *next;
ListNode(int val,ListNode *next=NULL):val(val),next(next){}
};
Java实现
public class ListNode {
public int val;
public ListNode next;
public ListNode(int val) {
this.val = val;
this.next = null;
}
}
"""
"""
反转链表
1->2->3->null 3->2->1->null
①访问某个节点curt.next时,要检验curt是否为null
②要把反转后的最后一个节点(即反转前的第一个节点指向null)
"""
'\n 反转链表\n 1->2->3->null 3->2->1->null\n ①访问某个节点curt.next时,要检验curt是否为null\n ②要把反转后的最后一个节点(即反转前的第一个节点指向null)\n'
class ListNode:
def __init__(self, val):
self.val = val
self.next = None
def reverse(self, head):
prev = None
while head:
temp = head.next
head.next = prev
prev = head
head = temp
return prev
"""
C++实现
ListNode * ReverseList(ListNode *head){
ListNode *pre=NULL,*tmp;
while(head){
tmp=head->next;
head->next=pre;
pre=head;
head=tmp;
}
return pre;
}
Java实现
class ListNode {
int val;
ListNode next;
ListNode(int val) {
this.val = val;
}
}
// iterative method
public ListNode reverse(ListNode head) {
ListNode prev = null;
while (head != null) {
ListNode next = head.next;
head.next = prev;
prev = head;
head = next;
}
return prev;
}
// recursive method
public ListNode reverse(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode next = head.next;
ListNode newHead = reverse(next);
next.next = head;
head.next = null;
return newHead;
}
"""
"""
双向链表跟单向链表的核心在于next和prev域的交换,还需要注意是当前节点和上一个节点的递推
"""
'\n 双向链表跟单向链表的核心在于next和prev域的交换,还需要注意是当前节点和上一个节点的递推\n'
class DListNode:
def __init__(self, val):
self.val = val
self.prev = self.next = null
def reverse(self, head):
curt = None
while head:
curt = head
Linked List
head = curt.next
curt.next = curt.prev
curt.prev = head
return curt
"""
Java实现
class DListNode {
int val;
DListNode prev, next;
DListNode(int val) {
this.val = val;
this.prev = this.next = null;
}
}
public DListNode reverse(DListNode head) {
DListNode curr = null;
while (head != null) {
curr = head;
head = curr.next;
curr.next = curr.prev;
curr.prev = head;
}
return curr;
}
"""
"""
二叉树是每个节点最多有两个子树的树结构,子树有左右之分,
二叉树常被用于实现二叉查找树和二叉堆
满二叉树:一个深度为K,且有2^k-1个节点称之为满二叉树
完全二叉树:深度为k,有n个节点的二叉树,当且仅当其每一个节点都与深度为k
的满二叉树中序号为1到n的节点对应时,称之为完全二叉树(若设二叉树的深度
为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有
的结点都连续集中在最左边,这就是完全二叉树)
"""
'\n 二叉树是每个节点最多有两个子树的树结构,子树有左右之分,\n 二叉树常被用于实现二叉查找树和二叉堆\n'
class TreeNode:
def __init__(self,val):
self.val=val
self.left,self.right=None,None
"""
C++实现
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
Java实现
public class TreeNode {
public int val;
public TreeNode left, right;
public TreeNode(int val) {
this.val = val;
this.left = null;
this.right = null;
}
}
"""
"""
树的遍历:
按照访问根元素的前后顺序,遍历方式可以划分为:
①深度优先
1.前序(pre-order):先根后左再右
2.中序(in-order):先左后根再右
3.后序(post-order):先左后右再根
②广度优先:先访问根节点,沿着树的宽度遍历子节点,直到所有的节点均被
访问为止(从左往右 从上往下)
⼆叉树的⼴度优先遍历和树的前序/中序/后序遍历不太⼀样,前/中/后序遍历使⽤递归,也就是栈的思
想对⼆叉树进⾏遍历,⼴度优先⼀般使⽤队列的思想对⼆叉树进⾏遍历。
"""
'\n 树的遍历:\n 按照访问根元素的前后顺序,遍历方式可以划分为:\n ①深度优先\n 1.前序(pre-order):先根后左再右\n 2.中序(in-order):先左后根再右\n 3.后序(post-order):先左后右再根\n ②广度优先:先访问根节点,沿着树的宽度遍历子节点,直到所有的节点均被\n 访问为止\n'
def factorial(n):
if(n<=1):
return 1
else:
subSolution=factorial(n-1)
solution=subSolution*n
return solution
factorial(6)
720
class Traversal(object):
def __init__(self):
self.traverse_path=list()
def preorder(self,root):
if root:
selft.traverse_path.append(root.val)
self.preorder(root.left)
self.preorder(root.right)
def inorder(self,root):
if root:
self.inorder(root.left)
self.traverse_path.append(root.val)
self.inorder(root.right)
def postorder(self,root):
if root:
self.postorder(root.left)
self.postorder(root.right)
self.traverse_path.append(root.val)
"""
Binary Search Tree 二叉查找树(BST)
是一棵二叉树,其中每个节点都含有一个可进行比较的键及相应的值,且每个
节点的键都大于等于左子树中任意节点的键
可参考网址:https://www.cs.usfca.edu/~galles/visualization/BST.html
"""
'\n Binary Search Tree 二叉查找树(BST)\n 是一棵二叉树,其中每个节点都含有一个可进行比较的键及相应的值,且每个\n 节点的键都大于等于左子树中任意节点的键\n'
"""
压缩算法Huffman算法
01100010 01100101 ....
beep boop beer!
字符 次数
'b' 3
'e' 4
'p' 2
'' 2
'o' 2
'r' 1
'!' 1
然后将这些东西放到Priority Queue中(用出现的次数当priority)可以看到
priority Queue是以Priority排序的一个数组,如果Priority一样,会使用
出现的次序排序
接下来通过算法把这个priority Queue转化成二叉树,始终从queue的头
取两个元素来构造一个二叉树(第一个元素是左节点,第二个元素是右节点)
并把这两个元素的priority相加,并且放回到priority中(priority就是
字符出现的次数)
最终得到编码表:
字符 编码
b 00
e 11
p 101
'' 010
! 1001
o 011
r 1000
注意:encode时候按照bit来进行encode,decode也是通过bit来完成
比如:有这样的bitset 1011110111 解码后就是唯一的字符pepe
pop 101011101
1011110111 pepe
"""
"""
a
0
ab
0 1
abc
00 01 10
abcd
00 01 10 11
ASCII 8*20=160
简单编码
e v r y d a '' i s w o m !
0000 0001 0010 ....
everyday is awesome!
"""
"\n a\n 0\n ab\n 0 1\n abc\n 00 01 10\n abcd\n 00 01 10 11\n\n ASCII 8*20=160\n \n 简单编码\n e v r y d a '' i s w o m !\n 0000 0001 0010 ....\n \n everyday is awesome!\n"
class SimpleCompression:
def __init__(self,string):
self.symbols=set(string)
self.bit_len=1
while 2**self.bit_len<len(self.symbols):
self.bit_len+=1
self.string=string
self.s2b={}
self.b2s={}
i=0
for s in self.symbols:
b=bin(i)[2:]
if len(b) < self.bit_len:
b=(self.bit_len-len(b))*'0'+b
self.s2b[s]=b
self.b2s[b]=s
i+=1
def compress(self):
bits=''
for s in self.string:
bits+=self.s2b[s]
return bits
def uncompress(self,bits):
string =''
for i in range(0,len(bits),self.bit_len):
string+=self.b2s[bits[i:i+self.bit_len]]
return string
import heapq
import collections
collections.Counter("ssadafagsfda")
Counter({'a': 4, 'd': 2, 'f': 2, 'g': 1, 's': 3})
import heapq
import collections
class HuffmanCompression:
class Trie:
def __init__(self, val, char=''):
self.val = val
self.char = char
self.coding = ''
self.left = self.right = None
def __eq__(self, other):
return self.val == other.val
def __lt__(self, other):
return self.val < other.val
def __gt__(self, other):
return self.val > other.val
def __init__(self, string):
self.string = string
counter = collections.Counter(string)
heap = []
for char, cnt in counter.items():
heapq.heappush(heap, HuffmanCompression.Trie(cnt, char))
while len(heap) != 1:
left = heapq.heappop(heap)
right = heapq.heappop(heap)
trie = HuffmanCompression.Trie(left.val + right.val)
trie.left, trie.right = left, right
heapq.heappush(heap, trie)
self.root = heap[0]
self.s2b = {}
self.bfs_encode(self.root, self.s2b)
def bfs_encode(self, root, s2b):
queue = collections.deque()
queue.append(root)
while queue:
node = queue.popleft()
if node.char:
s2b[node.char] = node.coding
continue
if node.left:
node.left.coding = node.coding + '0'
queue.append(node.left)
if node.right:
node.right.coding = node.coding + '1'
queue.append(node.right)
def compress(self):
bits = ''
for char in self.string:
bits += self.s2b[char]
return bits
def uncompress(self, bits):
string = ''
root = self.root
for bit in bits:
if bit == '0':
root = root.left
else:
root = root.right
if root.char:
string += root.char
root = self.root
return string
def get_rate(compressed_binary,uncompressed_bits):
return len(compressed_binary)*100/uncompressed_bits
if __name__ == '__main__':
s='everyday is awesome!'
bits=len(s)*8
print('Total bits :%d'%bits)
sc=SimpleCompression(s)
compressed=sc.compress()
print('Compressed binary:'+compressed)
print('Uncompressed :'+sc.uncompress(compressed))
print(sc.s2b)
print('Simple Compression-compress rate: %d%%'%get_rate(compressed,bits))
print('--------------------Huffman compression-------------------')
hc=HuffmanCompression(s)
compressed=hc.compress();
print('Compressed binary:'+compressed)
print("UnCompressed:"+hc.uncompress(compressed))
print(hc.s2b)
print("Huffman Compression-compress rate :%d%%"%get_rate(compressed,bits))
Total bits :160
Compressed binary:10011011100100000010000101100010101000110100101001101000100101000111010110011100
Uncompressed :everyday is awesome!
{'r': '0000', 'd': '0001', 'y': '0010', 'i': '0011', 's': '0100', 'm': '0101', 'a': '0110', 'o': '0111', 'w': '1000', 'e': '1001', ' ': '1010', 'v': '1011', '!': '1100'}
Simple Compression-compress rate: 50%
--------------------Huffman compression-------------------
Compressed binary:011101001110111111000011101111110010110011100111000010100110101000011001
UnCompressed:everyday is awesome!
{'e': '01', 's': '001', 'd': '0000', 'w': '0001', 'm': '1000', '!': '1001', 'o': '1010', 'i': '1011', ' ': '1100', 'a': '1110', 'y': '1111', 'v': '11010', 'r': '11011'}
Huffman Compression-compress rate :45%
s="everyday is awesome!"
sc=SimpleCompression(s)
sc.uncompress("010000101100")
's'
'sy'
'sy!'
'sy!'
s="everyday is awesome!"
sc=SimpleCompression(s)
print(sc.compress())
{' ', '!', 'a', 'd', 'e', 'i', 'm', 'o', 'r', 's', 'v', 'w', 'y'}
10011011100100000010000101100010101000110100101001101000100101000111010110011100
2*'0'+'10'
'0010'
print(bin(0)[2:])
print(bin(1)[2:])
print(bin(2)[2:])
print(bin(3)[2:])
print(bin(4)[2:])
"""
0 0000
1 0001
10 0010
11 0011
100 0100
"""
0
1
10
11
100
len(set("everyday is awesome!"))
13
set("everyday is awesome!")
{' ', '!', 'a', 'd', 'e', 'i', 'm', 'o', 'r', 's', 'v', 'w', 'y'}
"""
(先进先出)的数据结构,并发中使用较多,可以安全地将对象从一个任务传给另一个任务
编程实现:
Queue和stack在python中都是有list,实现的,list是一个动态数组,可以通过append在list尾部
添加元素,通过pop(0)在list首部弹出实现queue的FIFO
stack : FILO pop()尾部元素弹出实现stack操作
"""
queue=[]
size =len(queue)
display(size)
queue.append(1)
display(queue)
queue.append(2)
display(queue)
display(queue[0])
queue.pop(0)
display(queue)
display(queue[0])
queue.append(3)
display(queue)
queue.pop()
display(queue)
0
[1]
[1, 2]
1
[2]
2
[2, 3]
[2]
"""
Priority Queue 优先队列
应用程序常常需要处理带有优先级的业务,优先级最高的业务首先得到服务因此优先队列这种数据
结构应运而生。优先队列中每个元素都有自己的优先级,优先级最高的元素最先得到服务;优先级
相同的元素按照其在优先队列中顺序得到服务
优先队列可以使用数组或者链表实现,从时间和空间复杂度来说,往往用二叉堆来实现
python中提供了heapq的lib来实现priority queue,提供push,pop两个基本操作和heapify初始
化操作
Java中提供了一个PriorityQueue类
"""
"""
methods
enqueue heapq.push(queue,e)
dequeue heapq.pop(queue)
"""
"""
Deque-双端队列
双端队列可以让在任何一端添加或者移除元素,因此它是一种具有队列和栈性质的数据结构
python:
list就是可以执行类似于deque的操作,但是效率会比较慢,为了提高数据处理效率,
collections中提供了deque的类,建议在用list时多次执行头尾操作,请使用deque
Java:Deque类操作
"""
dq=collections.deque()