├── .idea
├── AlgorithmsByPython.iml
├── misc.xml
├── modules.xml
├── vcs.xml
└── workspace.xml
├── AVL.py
├── AnagramDetection.py
├── AwesomeAlgorithms
├── BoyerMoore算法.py
├── CatalanNumber.py
├── KMP算法.py
├── Sunday算法.py
├── manacher算法.py
├── 最长公共子串_DP问题.py
└── 最长公共子序列LCS_DP问题.py
├── BinaryHeap.py
├── BinarySearch.py
├── BinarySearchTree.py
├── BinaryTree.py
├── BubbleSort.py
├── CheckErrorWord.py
├── Dynamic Programming.py
├── Hash.py
├── InsertionSort.py
├── Lists.py
├── Logistic regression
├── Logistic.py
├── README.md
├── horseColicTest.txt
├── horseColicTraining.txt
└── testSet.txt
├── MapReduce_and_filter.py
├── MergeSort.py
├── ParseTree.py
├── Queue.py
├── QuickSort.py
├── README.md
├── RadixSort.py
├── Recursion.py
├── SVM
├── README.md
├── SVM.py
└── testSet.txt
├── SelectionSort.py
├── ShellSort.py
├── Stack.py
├── Target Offer
├── README.md
├── Singleton.py
├── multiSparse.py
├── n个骰子的点数.py
├── transSparseMatrix.py
├── 不用加减乘除做加法.py
├── 丑数.py
├── 两个链表的第一个公共结点.py
├── 二叉搜索树与双向链表.py
├── 二叉搜索树的后续遍历序列.py
├── 二叉搜索树的最低公共祖先.py
├── 二叉搜索树的第k个结点.py
├── 二叉树中和为某一值的路径.py
├── 二叉树的下一个结点.py
├── 二叉树的最低公共祖先.py
├── 二叉树的深度.py
├── 二叉树的镜像.py
├── 二维数组查找.py
├── 二进制中1的个数.py
├── 从上往下打印二叉树.py
├── 八皇后问题.py
├── 分治法解决最近对问题.py
├── 删除链表中重复的结点.py
├── 判断平衡二叉树.py
├── 包含min函数的栈.py
├── 反向打印链表.py
├── 反转链表.py
├── 句子中单词首字母大写.py
├── 合并两个排序的链表.py
├── 和为s的两个数字.py
├── 和为s的连续整数序列.py
├── 在O(1)时间内删除链表结点.py
├── 复杂链表的复制.py
├── 字符串具有相同字符的最长子串.py
├── 字符串的左旋转.py
├── 字符串的排列和组合.py
├── 字符流中第一个不重复的字符.py
├── 对称的二叉树.py
├── 带锁的门.py
├── 序列化二叉树.py
├── 扑克牌的顺子.py
├── 打印1到最大的n位数.py
├── 找出字符串中重复出现的最长子串.py
├── 把二叉树打印成多行.py
├── 把字符串转换成整数.py
├── 把数组排成最小的数.py
├── 按之字形顺序打印二叉树.py
├── 数值的整数次方.py
├── 数字在排序数组中出现的次数.py
├── 数据流中的中位数.py
├── 数组中出现次数超过一半的数字.py
├── 数组中只出现一次的数字.py
├── 数组中的逆序对.py
├── 数组中重复的数字.py
├── 整数中1出现的次数.py
├── 斐波那契数列.py
├── 旋转数组的最小数字.py
├── 替换空格.py
├── 最小的k个数.py
├── 机器人的运动范围.py
├── 构建乘积数组.py
├── 栈的压入弹出序列.py
├── 树的子结构.py
├── 树的宽度.py
├── 格雷码.py
├── 正则表达式匹配.py
├── 正方体对面和相同.py
├── 求前n项和.py
├── 滑动窗口的最大值.py
├── 用两个栈实现队列.py
├── 用两个队列实现栈.py
├── 矩阵中的路径.py
├── 第一个只出现一次的字符.py
├── 约瑟夫环.py
├── 翻转单词顺序.py
├── 表示数值的字符串.py
├── 调整数组顺序使奇数位于偶数前面.py
├── 转换字符串格式.py
├── 输出连续质数序列.py
├── 连续子数组的最大和.py
├── 递归和非递归实现二叉搜索树的三种遍历.py
├── 重建二叉树.py
├── 链表中倒数第k个结点.py
├── 链表中环的入口结点.py
├── 零钱找零以及进阶
└── 顺时针打印矩阵.py
├── __pycache__
├── BinaryTree.cpython-34.pyc
├── Stack.cpython-34.pyc
└── mysingleton.cpython-35.pyc
├── divideAndConquer.py
├── heapSort.py
├── leetcode
├── 1. Two Sum.py
├── 101. Symmetric Tree.py
├── 102. Binary Tree Level Order Traversal.py
├── 103. Binary Tree Zigzag Level Order Traversal.py
├── 105. Construct Binary Tree from Preorder and Inorder Traversal.py
├── 106. Construct Binary Tree from Inorder and Postorder Traversal.py
├── 112. Path Sum.py
├── 113. Path Sum II.py
├── 13. Roman to Integer.py
├── 143. Reorder List.py
├── 15. 3Sum.py
├── 19. Remove Nth Node From End of List.py
├── 192.WordFrequency.sh
├── 2. Add Two Numbers.py
├── 203. Remove Linked List Elements.py
├── 21. Merge Two Sorted Lists.py
├── 226. Invert Binary Tree.py
├── 230. Kth Smallest Element in a BST.py
├── 239. Sliding Window Maximum.py
├── 24. Swap Nodes in Pairs.py
├── 292. Nim Game.py
├── 297. Serialize and Deserialize Binary Tree.py
├── 3. Longest Substring Without Repeating Characters.py
├── 300. Longest Increasing Subsequence.py
├── 322. Coin Change
├── 337. House Robber III
├── 344. Reverse String.py
├── 4. Median of Two Sorted Arrays
├── 5. Longest Palindromic Substring.py
├── 61. Rotate List
├── 67. AddBinary.py
├── 7. Reverse Integer QuestionEditorial Solution
├── 82. Remove Duplicates from Sorted List II.py
├── 83. Remove Duplicates from Sorted List.py
└── words.txt
├── mysingleton.py
├── regularExpression
├── .idea
│ ├── misc.xml
│ ├── modules.xml
│ ├── regularExpression.iml
│ └── workspace.xml
├── README.md
├── reTest.py
├── re模块其他方法.py
├── re练习.py
├── 正则表达式语法.py
└── 正则表达式语法2.py
├── 数据结构.md
└── 数据结构.mobi
/.idea/AlgorithmsByPython.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/AnagramDetection.py:
--------------------------------------------------------------------------------
1 | class AnagramDetection:
2 | # 先对两个字符串进行list化
3 | # 对字符串对应的两个list进行排序
4 | # 依次比较字符是否匹配
5 | def anagramSolution1(self, s1, s2):
6 | alist1 = list(s1)
7 | alist2 = list(s2)
8 |
9 | alist1.sort()
10 | alist2.sort()
11 |
12 | pos = 0
13 | matches = True
14 |
15 | while pos < len(s1) and matches:
16 | if alist1[pos] == alist2[pos]:
17 | pos = pos + 1
18 | else:
19 | matches = False
20 |
21 | return matches
22 |
23 | # 首先生成两个26个字母的list
24 | # 计算每个字母出现的次数并存入到相应的list中
25 | # 比较两个list是否相同
26 | def anagramSolution2(self, s1, s2):
27 | c1 = [0] * 26
28 | c2 = [0] * 26
29 |
30 | for i in range(len(s1)):
31 | pos = ord(s1[i]) - ord('a')
32 | c1[pos] = c1[pos] + 1
33 |
34 | for i in range(len(s2)):
35 | pos = ord(s2[i]) - ord('a')
36 | c2[pos] = c2[pos] + 1
37 |
38 | j = 0
39 | stillOK = True
40 | while j < 26 and stillOK:
41 | if c1[j] == c2[j]:
42 | j = j + 1
43 | else:
44 | stillOK = False
45 |
46 | return stillOK
47 |
48 | # 首先将两个字符串list化
49 | # 将两个list中的字符生成两个set
50 | # 比较两个set, 如果不相等直接返回false
51 | # 如果两个set相等, 比较每个set中字符在相应list中的个数, 个数不同返回false
52 | def anagramSolution3(self, s1, s2):
53 | alist1 = list(s1)
54 | alist2 = list(s2)
55 |
56 | aset1 = set(alist1)
57 | aset2 = set(alist2)
58 |
59 | if aset1 != aset2:
60 | return False
61 | else:
62 | for ch in aset1:
63 | if alist1.count(ch) != alist2.count(ch):
64 | return False
65 | return True
66 |
67 | s1 = 'abcde'
68 | s2 = 'acbde'
69 | test = AnagramDetection()
70 | print(test.anagramSolution1(s1, s2))
71 | print(test.anagramSolution2(s1, s2))
72 | print(test.anagramSolution3(s1, s2))
73 |
--------------------------------------------------------------------------------
/AwesomeAlgorithms/BoyerMoore算法.py:
--------------------------------------------------------------------------------
1 | # -*- coding:UTF-8 -*-
2 | '''
3 | 实现BM算法, 算法质量介于KMP和Sunday之间
4 | '''
5 | def BoyerMoore(original, pattern):
6 | if original == None or pattern == None or len(original) < len(pattern):
7 | return None
8 | len1, len2 = len(original), len(pattern)
9 | pAppear = []
10 | # 查找一个字符使用蛮力法即可
11 | if len2 == 1:
12 | for i in range(len1):
13 | if original[i] == pattern[0]:
14 | pAppear.append(i)
15 | else:
16 | badTable = badCharTable(pattern)
17 | goodTable = goodSuffixTable(pattern)
18 | index = len2 - 1
19 | while index < len1:
20 | indexOfP = len2 - 1
21 | while index < len1 and pattern[indexOfP] == original[index]:
22 | if indexOfP == 0:
23 | pAppear.append(index)
24 | index += len2 + 1
25 | indexOfP += 1
26 | continue
27 | index -= 1
28 | indexOfP -= 1
29 | if index < len1:
30 | index += max(goodTable[len2 - 1 - indexOfP], badTable[original[index]])
31 | return pAppear if pAppear else False
32 | '''
33 | 生成一个坏字符表, 移动距离分为两种
34 | 字符不在模式中, 移动的长度为模式的长度;
35 | 字符在模式中,移动的长度为模式中最右边对应待检测字符对应的模式中存在的此字符到最后一个字符的距离
36 | 对于BARBER,除了E,B,R,A的单元格分别为1,2,3,4之外,所有字符移动的单元格均为6
37 | '''
38 | def badCharTable(pattern):
39 | table = {}
40 | length = len(pattern)
41 | alphaBet = list(map(chr, range(32, 127))) # 利用map生成一个原始移动表, 对应字符为从SPACE到~, 使用UTF-8对应表
42 | for i in alphaBet:
43 | table[i] = length
44 | # 更改pattern中存在字符的对应移动距离
45 | for j in range(length-1):
46 | table[pattern[j]] = length - 1 - j
47 | return table
48 |
49 | '''
50 | 生成一个好后缀表
51 | '''
52 | def goodSuffixTable(pattern):
53 | length = len(pattern)
54 | tabel = [0] * length
55 | lastPrefixPosition, i = len(pattern), length - 1
56 | while i >= 0:
57 | if isPrefix(pattern, i):
58 | lastPrefixPosition = i
59 | tabel[length - 1 - i] = lastPrefixPosition - i + length - 1
60 | i -= 1
61 | for i in range(length-1):
62 | slen = suffixLength(pattern, i)
63 | tabel[slen] = length - 1 - i + slen
64 | return tabel
65 | '''
66 | 判断模式后面几个字符是否等于模式前面相应长度的字符
67 | '''
68 | def isPrefix(pattern, p):
69 | length, j = len(pattern), 0
70 | for i in range(p, length):
71 | if pattern[i] != pattern[j]:
72 | return False
73 | j += 1
74 | return True
75 | '''
76 | 判断前缀以及后缀的重复长度
77 | '''
78 | def suffixLength(pattern, p):
79 | length, samLen = len(pattern), 0
80 | i, j = p, length-1
81 | while i >= 0 and pattern[i] == pattern[j]:
82 | samLen += 1
83 | i -= 1
84 | j -= 1
85 | return samLen
86 | print(BoyerMoore('aaaaa', 'aa'))
--------------------------------------------------------------------------------
/AwesomeAlgorithms/CatalanNumber.py:
--------------------------------------------------------------------------------
1 | # -*- coding:utf-8 -*-
2 | '''
3 | 给出 n,问由 1...n 为节点组成的不同的二叉查找树有多少种?
4 | 本质上是求得一个卡特兰数列
5 | 卡特兰数列递推公式: F(n) = C(2n, n)/(n+1) = (2n)!/( (n+1)! * n! )
6 | 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190
7 | '''
8 |
9 |
10 | class Solution:
11 | def numTrees(self, n):
12 | # n为0的时候输出1
13 | if n == 0 or n == None:
14 | return 1
15 | return self.factorial(n << 1) // (self.factorial(n) * self.factorial(n + 1))
16 | # 定义一个函数求取n的阶乘
17 | def factorial(self, n):
18 | result = 1
19 | for i in range(1, n + 1):
20 | result *= i
21 | return result
22 |
23 | s = Solution()
24 | print(s.numTrees(0))
25 | print(s.numTrees(1))
26 | print(s.numTrees(2))
27 | print(s.numTrees(3))
28 | print(s.numTrees(4))
--------------------------------------------------------------------------------
/AwesomeAlgorithms/KMP算法.py:
--------------------------------------------------------------------------------
1 | # -*- coding:UTF-8 -*-
2 | '''
3 | 实现KMP算法
4 | '''
5 | def kmp(str1, str2):
6 | if str1 == None or str2 == None or len(str1) < len(str2):
7 | return False
8 | index = 0 # index为str2对应于每次开始的位置
9 | len1, len2 = len(str1), len(str2)
10 | moveTable = matchTable(list(str2))
11 | pAppear = []
12 | while index <= len1 - len2:
13 | tmpIndex = 0 # tmpIndex为str2中字符走到的位置
14 | while tmpIndex < len2 and str1[index+tmpIndex] == str2[tmpIndex]:
15 | tmpIndex += 1
16 | if tmpIndex == len2:
17 | pAppear.append(index)
18 | index += len2
19 | continue
20 | elif tmpIndex > 0:
21 | index += tmpIndex - moveTable[tmpIndex-1]
22 | else:
23 | index += 1
24 | return pAppear if pAppear else False
25 |
26 | # 生成KMP匹配表, 该表和next表不一样
27 | def matchTable(aList):
28 | length = len(aList)
29 | table = [0]*length
30 | index = 1
31 | while index < length:
32 | sameLen = 0
33 | while aList[:sameLen+1] == aList[index:index+sameLen+1]:
34 | sameLen += 1
35 | table[index+sameLen-1] = sameLen
36 | if sameLen != 0:
37 | index += sameLen
38 | else:
39 | index += 1
40 | return table
41 | # 更具有一般性的字符移动表
42 | def matchTable2(aList):
43 | length = len(aList)
44 | table = [0]*length
45 | index = 1
46 | while index < length:
47 | sameLen = 0
48 | while index+sameLen < length and aList[sameLen] == aList[index+sameLen]:
49 | sameLen += 1
50 | table[index+sameLen-1] = sameLen
51 | if sameLen != 0:
52 | index += sameLen
53 | else:
54 | index += 1
55 | return table
56 |
57 | print(kmp('aaaaa', 'aa'))
58 |
--------------------------------------------------------------------------------
/AwesomeAlgorithms/Sunday算法.py:
--------------------------------------------------------------------------------
1 | # -*- coding:UTF-8 -*-
2 | '''
3 | 字符串匹配算法, 比KMP简单而且快, 比BM算法也简单
4 | '''
5 | def Sunday(str1, str2):
6 | if str1 == None or str2 == None or len(str1) < len(str2):
7 | return None
8 | len1, len2 = len(str1), len(str2)
9 | pAppear, moveDict = [], matchDict(list(str2))
10 | indexStr1 = 0
11 | while indexStr1 <= len1 - len2:
12 | indexStr2 = 0
13 | while indexStr2 < len2 and str1[indexStr1 + indexStr2] == str2[indexStr2]:
14 | indexStr2 += 1
15 | if indexStr2 == len2:
16 | pAppear.append(indexStr1)
17 | indexStr1 += len2
18 | continue
19 | if indexStr1 + len2 >= len1:
20 | break
21 | elif str1[indexStr1+len2] not in moveDict.keys():
22 | indexStr1 += len2 + 1
23 | else:
24 | indexStr1 += moveDict[str1[indexStr1+len2]]
25 | return pAppear if pAppear else False
26 |
27 | def matchDict(aList):
28 | moveDict = {}
29 | length = len(aList)
30 | for i in range(length-1, -1, -1):
31 | if aList[i] not in moveDict.keys():
32 | moveDict[aList[i]] = length - i
33 | return moveDict
34 |
35 | print(Sunday('aaaaa', 'aa'))
--------------------------------------------------------------------------------
/AwesomeAlgorithms/manacher算法.py:
--------------------------------------------------------------------------------
1 | # -*- coding:UTF-8 -*-
2 | '''
3 | 神之算法-Manacher算法
4 | 求最长回文子串
5 | '''
6 |
7 |
8 | def manacher(s):
9 | if s == None or len(s) == 0:
10 | return
11 | # 预处理字符串, 把字符串中间和首尾都添加#号, 时的字符串长度变为奇数
12 | # 预处理后的字符串每个位置对应的最长回文串的半径 减去1 等于原始字符串该处对应的最长回文串的长度
13 | s = "#" + "#".join(s) + "#"
14 | curLongest = [0] * len(s) # 使用curLongest存储每个位置最长回文串半径
15 | maxRight, mid = 0, 0 # maxRight, mid分别存储之前步骤中所有回文子串所能到达的s最右端坐标以及种鸽回文串的对称轴位置
16 | maxLen = 0 # maxLen 记录当前的最长回文串的长度
17 | for i in range(len(s)):
18 | if i < maxRight:
19 | # i处于maxRight左边有两种情况
20 | # 1. 当前位置i和对称轴pos相对应的位置j在前面操作中拥有的最大回文串半径没有达到maxRight关于pos的对称位置, 此时curLongest[i]从curLongest[2 * mid - i]开始扩张
21 | # 2. 当前位置i和对称轴pos相对应的位置j在前面操作中拥有的最大回文串半径能够达到maxRight关于pos的对称位置, 此时curLongest[i]从maxRight-i的长度开始扩张
22 | curLongest[i] = min(curLongest[2 * mid - i], maxRight - i)
23 | else:
24 | # i处于maxRight的位置或者maxRight右边的位置时
25 | curLongest[i] = 1
26 | while i - curLongest[i] >= 0 and curLongest[i] + i < len(s) and s[i-curLongest[i]] == s[i+curLongest[i]]:
27 | curLongest[i] += 1
28 | # 如果当前i所对应的回文串最右边长度大于之前maxRight, 更新maxRight和对称轴的位置
29 | if curLongest[i] + i - 1 > maxRight:
30 | maxRight = curLongest[i] + i - 1
31 | mid = i
32 | maxLen = max(maxLen, curLongest[i])
33 | return maxLen - 1
34 | print(manacher('saas'))
--------------------------------------------------------------------------------
/AwesomeAlgorithms/最长公共子串_DP问题.py:
--------------------------------------------------------------------------------
1 | # -*- coding:utf-8 -*-
2 | '''
3 | 给出两个字符串,找到最长公共子串,并返回其长度。
4 | '''
5 |
6 | class Solution:
7 | # 动态规划解决最长公共子串问题
8 | # 时间复杂度O(m*n), 空间复杂度O(m*n)
9 | def longestCommonSubstring(self, A, B):
10 | if A == None or B == None or len(A) + len(B) == 0:
11 | return 0
12 | lenA, lenB = len(A), len(B)
13 | C = [[0] * (lenB+1) for i in range(lenA + 1)]
14 | maxLen, maxIndex = 0, 0
15 | for i in range(1, lenA + 1):
16 | for j in range(1, lenB + 1):
17 | if A[i-1] == B[j-1]:
18 | C[i][j] = C[i-1][j-1] + 1
19 | if C[i][j] > maxLen:
20 | maxLen = C[i][j]
21 | maxIndex = i - maxLen
22 | LCS = A[maxIndex:maxIndex + maxLen]
23 | return maxLen, LCS
24 | # 利用后缀数组解决最长公共子串问题
25 | def longestCommonSubstring2(self, A, B):
26 | if A == None or B == None:
27 | return
28 | s = A + "#" + B
29 | indexOfSharp = len(A)
30 | SA = self.suffixArray(s)
31 | maxLen, maxIndex = 0, 0
32 | hasCommon = False
33 | for i in range(len(s) - 1):
34 | diff = (SA[i] - indexOfSharp) * (SA[i + 1] - indexOfSharp)
35 | if diff < 0:
36 | tempLen = self.comlen(s, SA[i], SA[i + 1])
37 | if tempLen > maxLen:
38 | maxLen = tempLen
39 | maxIndex = SA[i]
40 | hasCommon = True
41 | return (maxLen, s[maxIndex:maxIndex + maxLen]) if hasCommon else False
42 | # 得到一个字符串的后缀数组
43 | def suffixArray(self, s):
44 | if s == None or len(s) == 0:
45 | return None
46 | allSuffix = []
47 | for i in range(len(s)):
48 | allSuffix.append([s[i:], i])
49 | sortedList = sorted(allSuffix)
50 | SA = [w[1] for w in sortedList]
51 | return SA
52 | # 比较得到后缀数组中两个相邻的元素分别对应的后缀字符串的最长前缀
53 | def comlen(self, s, p, q):
54 | j = 0
55 | while j < len(s[p:]) and j < len(s[q:]) and s[p:p + j + 1] == s[q:q + j + 1]:
56 | j += 1
57 | return j
58 |
59 | s = Solution()
60 | print(s.longestCommonSubstring("acbabc", "acaccbabb"))
61 | print(s.longestCommonSubstring2("acbabc", "acaccbabb"))
62 |
63 |
64 |
--------------------------------------------------------------------------------
/AwesomeAlgorithms/最长公共子序列LCS_DP问题.py:
--------------------------------------------------------------------------------
1 | # -*- coding:UTF-8 -*-
2 | '''
3 | 给出两个字符串,找到最长公共子序列(LCS),返回LCS的长度。
4 | 给出"ABCD" 和 "EDCA",这个LCS是 "A" (或 D或C),返回1
5 | 给出 "ABCD" 和 "EACB",这个LCS是"AC"返回 2
6 | '''
7 | class Solution:
8 | def longestCommonSubsequence(self, A, B):
9 | if A == None or B == None:
10 | return
11 | lenA, lenB = len(A), len(B)
12 | C = self.LCSLength(A, B)
13 | lcs = self.printLCS(C, A, B, lenA, lenB)
14 | return lcs
15 |
16 | def LCSLength(self, A, B):
17 | lenA, lenB = len(A), len(B)
18 | C = [[0]*(lenB+1) for i in range(lenA+1)]
19 | for i in range(1, lenA+1):
20 | for j in range(1, lenB+1):
21 | if A[i-1] == B[j-1]:
22 | C[i][j] = C[i-1][j-1] + 1
23 | elif C[i-1][j] >= C[i][j-1]:
24 | C[i][j] = C[i-1][j]
25 | else:
26 | C[i][j] = C[i][j-1]
27 | return C
28 | def printLCS(self, arr, A, B, lenA, lenB):
29 | if lenA == 0 or lenB == 0:
30 | return ""
31 | if A[lenA-1] == B[lenB-1]:
32 | s = self.printLCS(arr, A, B, lenA-1, lenB-1) + A[lenA-1]
33 | elif arr[lenA-1][lenB] >= arr[lenA][lenB-1]:
34 | s = self.printLCS(arr, A, B, lenA-1, lenB)
35 | else:
36 | s = self.printLCS(arr, A, B, lenA, lenB-1)
37 | return s
38 |
39 | s = Solution()
40 | print(s.longestCommonSubsequence("ABCBDAB", "BDCABA"))
41 |
--------------------------------------------------------------------------------
/BinaryHeap.py:
--------------------------------------------------------------------------------
1 | # 构建树实现堆
2 | class BinHeap:
3 | def __init__(self):
4 | self.heapList = [0]
5 | self.currentSize = 0
6 |
7 | #插入新结点后必要时交换子节点和父节点的位置保持堆的性质
8 | def percUp(self, i):
9 | while i//2 > 0:
10 | if self.heapList[i] < self.heapList[i//2]:
11 | temp = self.heapList[i//2]
12 | self.heapList[i//2] = self.heapList[i]
13 | self.heapList[i] = temp
14 | i = i//2
15 |
16 | # 插入节点
17 | def insert(self, k):
18 | self.heapList.append(k)
19 | self.currentSize += 1
20 | self.percUp(self.currentSize)
21 |
22 | # 删除堆顶元素后, 交换堆尾和空堆顶的位置并实现元素的下沉
23 | def percDown(self, i):
24 | while (i*2) <= self.currentSize:
25 | mc = self.minChild(i)
26 | if self.heapList[i] > self.heapList[mc]:
27 | temp = self.heapList[i]
28 | self.heapList[i] = self.heapList[mc]
29 | self.heapList[mc] = temp
30 | i = mc
31 |
32 | def minChild(self, i):
33 | if i * 2 + 1 > self.currentSize:
34 | return i * 2
35 | else:
36 | if self.heapList[i*2] < self.heapList[i*2+1]:
37 | return i * 2
38 | else:
39 | return i * 2 + 1
40 |
41 | def delMin(self):
42 | retval = self.heapList[1]
43 | self.heapList[1] = self.heapList[self.currentSize]
44 | self.currentSize = self.currentSize - 1
45 | self.heapList.pop()
46 | self.percDown(1)
47 | return retval
48 |
49 | def buildHeap(self, alist):
50 | i = len(alist) // 2
51 | self.currentSize = len(alist)
52 | self.heapList = [0] + alist[:]
53 | while (i > 0):
54 | self.percDown(i)
55 | i = i - 1
56 | return self.heapList
57 |
58 | H = BinHeap()
59 | print(H.buildHeap([9, 6, 5, 2, 3]))
--------------------------------------------------------------------------------
/BinarySearch.py:
--------------------------------------------------------------------------------
1 | # 实现一个二分查找
2 | # 输入:一个顺序list
3 | # 输出: 待查找的元素的位置
4 | def binarySearch(alist, item):
5 | first = 0
6 | last = len(alist) - 1
7 |
8 | while first <= last:
9 | mid = (first + last)//2
10 | print(mid)
11 | if alist[mid] > item:
12 | last = mid - 1
13 | elif alist[mid] < item:
14 | first = mid + 1
15 | else:
16 | return mid+1
17 | return -1
18 |
19 | test = [0, 1, 2, 8, 13, 17, 19, 32, 42]
20 | print(binarySearch(test, 3))
--------------------------------------------------------------------------------
/BinaryTree.py:
--------------------------------------------------------------------------------
1 | class BinaryTree:
2 | def __init__(self, rootObj):
3 | self.key = rootObj
4 | self.leftChild = None
5 | self.rightChild = None
6 |
7 | def insertLeft(self, newNode):
8 | if self.leftChild == None:
9 | self.leftChild = BinaryTree(newNode)
10 | else:
11 | t = BinaryTree(newNode)
12 | t.leftChild = self.leftChild
13 | self.leftChild = t
14 |
15 | def insertRight(self, newNode):
16 | if self.rightChild == None:
17 | self.rightChild = BinaryTree(newNode)
18 | else:
19 | t = BinaryTree(newNode)
20 | t.rightChild = self.rightChild
21 | self.rightChild = t
22 |
23 | def getRightChild(self):
24 | return self.rightChild
25 |
26 | def getLeftChild(self):
27 | return self.leftChild
28 |
29 | def setRootVal(self, obj):
30 | self.key = obj
31 |
32 | def getRootVal(self):
33 | return self.key
34 |
35 | # 树的前序遍历
36 | # 树的后序遍历以及中序遍历见ParseTree.py
37 | def preorder(self):
38 | print(self.key)
39 | if self.leftChild:
40 | self.leftChild.preorder()
41 | if self.rightChild:
42 | self.rightChild.preorder()
43 |
44 | '''
45 | 以下为测试数据, 去掉 # 即可
46 | '''
47 | # r = BinaryTree('a')
48 | # print(r.getRootVal())
49 | # print(r.getLeftChild())
50 | # r.insertLeft('b')
51 | # print(r.getLeftChild())
52 | # print(r.getLeftChild().getRootVal())
53 | # r.insertRight('c')
54 | # print(r.getRightChild())
55 | # print(r.getRightChild().getRootVal())
56 | # r.getRightChild().setRootVal('hello')
57 | # print(r.getRightChild().getRootVal())
58 |
59 |
--------------------------------------------------------------------------------
/BubbleSort.py:
--------------------------------------------------------------------------------
1 | # Python 实现冒泡排序
2 | def bubbleSort(alist):
3 | for passnum in range(len(alist)-1, 0, -1):
4 | for i in range(passnum):
5 | if alist[i] > alist[i+1]:
6 | alist[i], alist[i+1] = alist[i+1], alist[i]
7 | return alist
8 |
9 | alist = [54,26,93,17,77,31,44,55,20]
10 | print(bubbleSort(alist))
11 |
12 | # 改进的冒泡排序, 加入一个校验, 如果某次循环发现没有发生数值交换, 直接跳出循环
13 | def modiBubbleSort(alist):
14 | exchange = True
15 | passnum = len(alist) - 1
16 | while passnum >= 1 and exchange:
17 | exchange = False
18 | for i in range(passnum):
19 | if alist[i] > alist[i+1]:
20 | alist[i], alist[i+1] = alist[i+1], alist[i]
21 | exchange = True
22 | passnum -= 1
23 | return alist
24 |
25 | print(bubbleSort(alist))
--------------------------------------------------------------------------------
/CheckErrorWord.py:
--------------------------------------------------------------------------------
1 | # 网传鹅厂面试题,英语单词拼写检查算法
2 | # 比如输入hello, 却错误的输入了hellu, 找出出错的字母
3 | # 感谢知乎知友@Lee Shellay
4 |
5 | # 对词典中的每个词, 逐刺逐字母拓展Trie, 单词完结处结点用END符号标识
6 | END = '$'
7 |
8 | def make_trie(words):
9 | trie = {}
10 | for word in words:
11 | t = trie
12 | for c in word:
13 | if c not in t:
14 | t[c] = {}
15 | t = t[c]
16 | t[END] = {}
17 | return trie
18 |
19 | # 容错查找
20 | # 实质上是对Trie的深度优先搜索,每一步加深时就消耗目标词的一个字母
21 | # 当搜索到达某个结点时,分为不消耗容错数和消耗容错数的的情形,继续搜索知道目标词为空。
22 | # 搜索过程中,用path记录搜索路径,该路径及为一个词典中存在的词,作为纠错的参考
23 | # 最终结果即为诸多搜索停止位置的结点路径的并集
24 | def check_fuzzy(trie, word, path='', tol=1): #tol为容错数
25 | if word == '':
26 | return [path] if END in trie else []
27 | else:
28 | p0 = []
29 | if word[0] in trie:
30 | p0 = check_fuzzy(trie[word[0]], word[1:], path+word[0], tol)
31 | p1 = []
32 | if tol > 0:
33 | for k in trie:
34 | if k != word[0]:
35 | p1.extend(check_fuzzy(trie[k], word[1:], path+k, tol-1))
36 | return p0 + p1
37 |
38 |
39 | # 测试代码
40 | words = ['hello', 'hela', 'dome']
41 | t = make_trie(words)
42 | print(t)
43 | print(check_fuzzy(t, 'hellu'))
44 | print(check_fuzzy(t, 'healu', tol=2))
--------------------------------------------------------------------------------
/Dynamic Programming.py:
--------------------------------------------------------------------------------
1 | # 解决动态规划中的找零问题
2 | # 输入需要找零的金额和货币的币值向量
3 | # 输出满足找零条件的最少的硬币个数
4 | def ChangeMaking(coinVal, change):
5 | alist = [0]*(change+1)
6 | for i in range(1, change+1):
7 | temp = change; j = 0
8 | while j <= len(coinVal)-1 and i >= coinVal[j]:
9 | temp = min(alist[i-coinVal[j]], temp)
10 | j += 1
11 | alist[i] = temp + 1
12 | return alist.pop()
13 |
14 | print(ChangeMaking([1, 5, 10, 25], 63))
15 |
16 | # 解决动态规划中的币值最大化问题---在满足所选硬币不相邻的条件下,从一堆硬币中选择最大金额的硬币
17 | # 输入数组C[1..n]保存n个硬币的面值
18 | # 输出可选硬币的最大金额
19 | def coinRow(coinrow):
20 | alist = [0]*(len(coinrow)+1)
21 | alist[1] = coinrow[0]
22 | for i in range(2, len(coinrow)+1):
23 | alist[i] = max(coinrow[i-1]+alist[i-2], alist[i-1])
24 | return alist.pop()
25 |
26 | print(coinRow([5, 1, 2, 10, 6, 2]))
27 |
28 | # 解决0-1背包问题
29 | def maxBag(weight, value, totalWeight):
30 | if len(weight) <= 0 or len(value) <= 0 or totalWeight <= 0 or len(weight) != len(value):
31 | return
32 | num = len(weight)
33 | tempMat = []
34 | for i in range(num+1):
35 | tempMat.append([0]*(totalWeight+1))
36 | for i in range(1, num+1):
37 | for j in range(1, totalWeight+1):
38 | if j - weight[i-1] >= 0:
39 | tempMat[i][j] = max(tempMat[i-1][j], value[i-1] + tempMat[i-1][j-weight[i-1]])
40 | else:
41 | tempMat[i][j] = tempMat[i-1][j]
42 | return tempMat[-1][-1]
43 |
44 | weight, value, totalWeight = [2,1,3,2], [12,10,20,15], 5
45 | print(maxBag(weight, value, totalWeight))
--------------------------------------------------------------------------------
/InsertionSort.py:
--------------------------------------------------------------------------------
1 | def insertionSort(alist):
2 | for key, item in enumerate(alist):
3 | index = key
4 | while index > 0 and alist[index-1] > item:
5 | alist[index] = alist[index-1]
6 | index -= 1
7 | alist[index] = item
8 | return alist
9 |
10 | alist = [54,26,93,17,77,31,44,55,20]
11 | print(insertionSort(alist))
12 |
13 | def insertionSort2(alist):
14 | for index in range(1, len(alist)):
15 | currentvalue = alist[index]
16 | position = index
17 |
18 | while position > 0 and alist[position-1] > currentvalue:
19 | alist[position] = alist[position-1]
20 | position -= 1
21 | alist[position] = currentvalue
22 |
23 | return alist
24 |
25 | print(insertionSort2(alist))
26 |
--------------------------------------------------------------------------------
/Lists.py:
--------------------------------------------------------------------------------
1 | class Node:
2 | def __init__(self, initdata):
3 | self.data = initdata
4 | self.next = None
5 |
6 | def getData(self):
7 | return self.data
8 |
9 | def getNext(self):
10 | return self.next
11 |
12 | def setData(self, newdata):
13 | self.next = newdata
14 |
15 | def setNext(self, nextNode):
16 | self.next = nextNode
17 |
18 |
19 | temp = Node(93)
20 | temp.setData(10)
21 | print(temp.getNext())
22 |
23 | # 定义一个无序链表
24 | class UnorderedList:
25 | def __init__(self):
26 | self.head = None
27 |
28 | def isEmpty(self):
29 | return self.head == None
30 |
31 | def add(self, item):
32 | temp = Node(item)
33 | temp.setNext(self.head)
34 | self.head = temp
35 |
36 | def size(self):
37 | current = self.head
38 | count = 0
39 | while current != None:
40 | count += 1
41 | current = current.getNext()
42 | return count
43 |
44 | def search(self, item):
45 | current = self.head
46 | found = False
47 | while current != None and not found:
48 | if current.getData() == item:
49 | found = True
50 | else:
51 | current = current.getNext()
52 | return found
53 |
54 | def remove(self, item):
55 | current = self.head
56 | previous = None
57 | found = False
58 | while not found:
59 | if current.getData() == item:
60 | found = True
61 | else:
62 | previous = current
63 | current = current.getNext()
64 |
65 | if previous == None:
66 | self.head = current.getNext()
67 | else:
68 | previous.setNext(current.getNext())
69 |
70 | myList = UnorderedList()
71 | myList.add(31)
72 | myList.add(77)
73 | myList.add(17)
74 | myList.add(93)
75 | myList.add(26)
76 | myList.add(54)
77 | print(myList.search(17))
78 | myList.remove(54)
79 | print(myList.search(54))
--------------------------------------------------------------------------------
/Logistic regression/README.md:
--------------------------------------------------------------------------------
1 | # #Python实现逻辑斯蒂回归
2 | 使用Python实现Logistic回归,代码思路来源于[机器学习实战](https://github.com/pbharrin/machinelearninginaction),改正了原代码中的一些在Python3.5上运行存在的bug。对随机梯度上升法进行了简单的修改。
--------------------------------------------------------------------------------
/Logistic regression/testSet.txt:
--------------------------------------------------------------------------------
1 | -0.017612 14.053064 0
2 | -1.395634 4.662541 1
3 | -0.752157 6.538620 0
4 | -1.322371 7.152853 0
5 | 0.423363 11.054677 0
6 | 0.406704 7.067335 1
7 | 0.667394 12.741452 0
8 | -2.460150 6.866805 1
9 | 0.569411 9.548755 0
10 | -0.026632 10.427743 0
11 | 0.850433 6.920334 1
12 | 1.347183 13.175500 0
13 | 1.176813 3.167020 1
14 | -1.781871 9.097953 0
15 | -0.566606 5.749003 1
16 | 0.931635 1.589505 1
17 | -0.024205 6.151823 1
18 | -0.036453 2.690988 1
19 | -0.196949 0.444165 1
20 | 1.014459 5.754399 1
21 | 1.985298 3.230619 1
22 | -1.693453 -0.557540 1
23 | -0.576525 11.778922 0
24 | -0.346811 -1.678730 1
25 | -2.124484 2.672471 1
26 | 1.217916 9.597015 0
27 | -0.733928 9.098687 0
28 | -3.642001 -1.618087 1
29 | 0.315985 3.523953 1
30 | 1.416614 9.619232 0
31 | -0.386323 3.989286 1
32 | 0.556921 8.294984 1
33 | 1.224863 11.587360 0
34 | -1.347803 -2.406051 1
35 | 1.196604 4.951851 1
36 | 0.275221 9.543647 0
37 | 0.470575 9.332488 0
38 | -1.889567 9.542662 0
39 | -1.527893 12.150579 0
40 | -1.185247 11.309318 0
41 | -0.445678 3.297303 1
42 | 1.042222 6.105155 1
43 | -0.618787 10.320986 0
44 | 1.152083 0.548467 1
45 | 0.828534 2.676045 1
46 | -1.237728 10.549033 0
47 | -0.683565 -2.166125 1
48 | 0.229456 5.921938 1
49 | -0.959885 11.555336 0
50 | 0.492911 10.993324 0
51 | 0.184992 8.721488 0
52 | -0.355715 10.325976 0
53 | -0.397822 8.058397 0
54 | 0.824839 13.730343 0
55 | 1.507278 5.027866 1
56 | 0.099671 6.835839 1
57 | -0.344008 10.717485 0
58 | 1.785928 7.718645 1
59 | -0.918801 11.560217 0
60 | -0.364009 4.747300 1
61 | -0.841722 4.119083 1
62 | 0.490426 1.960539 1
63 | -0.007194 9.075792 0
64 | 0.356107 12.447863 0
65 | 0.342578 12.281162 0
66 | -0.810823 -1.466018 1
67 | 2.530777 6.476801 1
68 | 1.296683 11.607559 0
69 | 0.475487 12.040035 0
70 | -0.783277 11.009725 0
71 | 0.074798 11.023650 0
72 | -1.337472 0.468339 1
73 | -0.102781 13.763651 0
74 | -0.147324 2.874846 1
75 | 0.518389 9.887035 0
76 | 1.015399 7.571882 0
77 | -1.658086 -0.027255 1
78 | 1.319944 2.171228 1
79 | 2.056216 5.019981 1
80 | -0.851633 4.375691 1
81 | -1.510047 6.061992 0
82 | -1.076637 -3.181888 1
83 | 1.821096 10.283990 0
84 | 3.010150 8.401766 1
85 | -1.099458 1.688274 1
86 | -0.834872 -1.733869 1
87 | -0.846637 3.849075 1
88 | 1.400102 12.628781 0
89 | 1.752842 5.468166 1
90 | 0.078557 0.059736 1
91 | 0.089392 -0.715300 1
92 | 1.825662 12.693808 0
93 | 0.197445 9.744638 0
94 | 0.126117 0.922311 1
95 | -0.679797 1.220530 1
96 | 0.677983 2.556666 1
97 | 0.761349 10.693862 0
98 | -2.168791 0.143632 1
99 | 1.388610 9.341997 0
100 | 0.317029 14.739025 0
101 |
--------------------------------------------------------------------------------
/MapReduce_and_filter.py:
--------------------------------------------------------------------------------
1 | # -*- coding:UTF-8 -*-
2 | import functools
3 | # Python3.x和Python2.x对于map、reduce、filter的处理变得不同
4 | # Python3.x中map和filter的输出是一个map型和filter型, 需要从里面取出需要的值
5 | # Python2.x中map和filter输出的直接是一个list
6 | # Python3.x中使用reduce需要引入functools
7 |
8 | # 使用map把list中的int变为str
9 | map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])
10 | # 使用map()把名字规范化, 首字母大写,其余小写
11 | def standardName(s):
12 | return s.capitalize()
13 | print([x for x in map(standardName, ['adam', 'LISA', 'barT'])])
14 | # 在Python2.x中应该使用print(map(standardName, ['adam', 'LISA', 'barT']))
15 |
16 | # 使用reduce()输出一个list的所有数的乘积
17 | def prod(aList):
18 | return functools.reduce(lambda x, y: x*y, aList)
19 | print(prod([1, 2, 3, 4, 5]))
20 |
21 | # 使用filter()打印100以内的素数
22 | def isPrime(n):
23 | isPrimeFlag = True
24 | if n <= 1:
25 | isPrimeFlag = False
26 | i = 2
27 |
28 | while i * i <= n:
29 | if n % i == 0:
30 | isPrimeFlag = False
31 | break
32 | i += 1
33 | return n if isPrimeFlag else None
34 | print(filter(isPrime, range(101)))
--------------------------------------------------------------------------------
/MergeSort.py:
--------------------------------------------------------------------------------
1 | def mergeSort(alist):
2 | if len(alist) > 1:
3 | mid = len(alist)//2
4 | lefthalf = alist[:mid]
5 | righthalf = alist[mid:]
6 |
7 | mergeSort(lefthalf)
8 | mergeSort(righthalf)
9 |
10 | i = 0; j = 0; k = 0
11 | while i < len(lefthalf) and j < len(righthalf):
12 | if lefthalf[i] < righthalf[j]:
13 | alist[k] = lefthalf[i]
14 | i += 1
15 | else:
16 | alist[k] = righthalf[j]
17 | j += 1
18 | k += 1
19 |
20 | while i < len(lefthalf):
21 | alist[k] = lefthalf[i]
22 | i += 1
23 | k += 1
24 | while j < len(righthalf):
25 | alist[k] = righthalf[j]
26 | j += 1
27 | k += 1
28 |
29 | alist = [54,26,93,17,77,31,44,55,20]
30 | mergeSort(alist)
31 | print(alist)
--------------------------------------------------------------------------------
/Queue.py:
--------------------------------------------------------------------------------
1 | class Queue:
2 | def __init__(self):
3 | self.items = []
4 |
5 | def isEmpty(self):
6 | return self.items == []
7 |
8 | def enqueue(self, item):
9 | self.items.insert(0, item)
10 |
11 | def dequeue(self):
12 | return self.items.pop()
13 |
14 | def size(self):
15 | return len(self.items)
16 |
17 | q = Queue()
18 | q.enqueue(4)
19 | q.enqueue('god')
20 | q.enqueue(True)
21 | print(q.dequeue())
22 |
23 | def hotPotato(namelist, num):
24 | simqueue = Queue()
25 | for name in namelist:
26 | simqueue.enqueue(name)
27 |
28 | while simqueue.size() > 1:
29 | for i in range(num):
30 | simqueue.enqueue(simqueue.dequeue())
31 | simqueue.dequeue()
32 |
33 | return simqueue.dequeue()
34 |
35 | print(hotPotato(["Bill","David","Susan","Jane","Kent","Brad"],7))
36 |
37 | # 设计一个良策都能插入删除的队列deque
38 | class Deque:
39 | def __init__(self):
40 | self.items = []
41 |
42 | def isEmpty(self):
43 | return self.items == []
44 |
45 | def addRear(self, item):
46 | self.items.insert(0, item)
47 |
48 | def addFront(self, item):
49 | self.items.append(item)
50 |
51 | def removeFront(self):
52 | return self.items.pop()
53 |
54 | def removeRear(self):
55 | return self.items.pop(0)
56 |
57 | def size(self):
58 | return len(self.items)
59 |
60 | # 利用Deque解决回文字符串
61 | def palcheker(aString):
62 | chardeque = Deque()
63 |
64 | for ch in aString:
65 | chardeque.addFront(ch)
66 |
67 | stillEqual = True
68 |
69 | while chardeque.size() > 1 and stillEqual:
70 | first = chardeque.removeFront()
71 | last = chardeque.removeRear()
72 | if first != last:
73 | stillEqual = False
74 |
75 | return stillEqual
76 |
77 | print(palcheker('lsdkjfskf'))
78 | print(palcheker('radar'))
--------------------------------------------------------------------------------
/QuickSort.py:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 |
3 | def quickSort(alist):
4 | quickSortHelper(alist, 0, len(alist)-1)
5 |
6 | def quickSortHelper(alist, first, last):
7 | if first < last:
8 | splitPoint = partition(alist, first, last)
9 |
10 | quickSortHelper(alist, first, splitPoint-1)
11 | quickSortHelper(alist, splitPoint+1, last)
12 |
13 | def partition(alist, first, last):
14 | pivotvlue = alist[first]
15 |
16 | leftmark = first+1
17 | rightmark = last
18 | done = False
19 |
20 | while not done:
21 | while leftmark <= rightmark and alist[leftmark] <= pivotvlue: # bugfix: 先比较index, 不然数组会越界
22 | leftmark += 1
23 | while rightmark >= leftmark and alist[rightmark] >= pivotvlue:
24 | rightmark -= 1
25 |
26 | if leftmark > rightmark:
27 | done = True
28 | else:
29 | alist[leftmark], alist[rightmark] = alist[rightmark], alist[leftmark]
30 | alist[rightmark], alist[first] = alist[first], alist[rightmark]
31 | return rightmark
32 |
33 | alist = [54,26,93,17,77,31,44,55,20]
34 | alist2 = [1]
35 | quickSort(alist2)
36 | print(alist2)
37 |
38 |
39 | if __name__ == "__main__":
40 | test_data = [3,2,111,3,-1,0,0,1,0,2,4]
41 |
42 | res_stable = sorted(test_data)
43 | quickSort(test_data)
44 | print(test_data)
45 | print(res_stable)
46 | assert all(map(lambda x: x[0] == x[1], zip(res_stable, test_data)))
--------------------------------------------------------------------------------
/RadixSort.py:
--------------------------------------------------------------------------------
1 | '''
2 | 实现基数排序RadixSort, 分为:
3 | 最高位优先(Most Significant Digit first)法
4 | 最低位优先(Least Significant Digit first)法
5 | '''
6 |
7 | # 最低位优先法
8 | def radixSortLSD(alist):
9 | if len(alist) == 0:
10 | return
11 | if len(alist) == 1:
12 | return alist
13 | tempList = alist
14 | maxNum = max(alist)
15 | radix = 10
16 | while maxNum * 10 > radix:
17 | newArr = [[], [], [], [], [], [], [], [], [], []]
18 | for n1 in tempList:
19 | testnum = n1 % radix
20 | testnum = testnum // (radix / 10)
21 | for n2 in range(10):
22 | if testnum == n2:
23 | newArr[n2].append(n1)
24 | tempList = []
25 | for i in range(len(newArr)):
26 | for j in range(len(newArr[i])):
27 | tempList.append(newArr[i][j])
28 | radix *= 10
29 | return tempList
30 |
31 |
32 |
33 | print(radixSortLSD([10, 12, 24, 23, 13, 52, 15, 158, 74, 32, 254, 201, 30, 19]))
34 |
--------------------------------------------------------------------------------
/Recursion.py:
--------------------------------------------------------------------------------
1 | # 递归求和
2 | def listSum(numlist):
3 | if len(numlist) == 1:
4 | return numlist[0]
5 | else:
6 | return numlist[0] + listSum(numlist[1:])
7 |
8 | print(listSum([1, 2, 3, 4, 5, 6, 7]))
9 |
10 | # 递归求阶乘
11 | def listFactorial(num):
12 | if num <= 1:
13 | return 1
14 | else:
15 | return num * listFactorial(num-1)
16 |
17 | print(listFactorial(10))
18 |
19 | # 递归实现进制转换:
20 | def toStr(n,base):
21 | convertString = "0123456789ABCDEF"
22 | if n < base:
23 | return convertString[n]
24 | else:
25 | return toStr(n//base, base) + convertString[n%base]
26 |
27 | print(toStr(1453, 16))
28 |
29 | # 递归实现Hanoi塔
30 | def Hanoi(fromPole, withPole, toPole, diskNum):
31 | if diskNum <= 1:
32 | print("moving disk from %s to %s" % (fromPole, toPole))
33 | else:
34 | Hanoi(fromPole, toPole, withPole, diskNum-1)
35 | print("moving disk from %s to %s" % (fromPole, toPole))
36 | Hanoi(withPole, fromPole, toPole, diskNum-1)
37 |
38 | Hanoi('A', 'B', 'C', 3)
39 |
--------------------------------------------------------------------------------
/SVM/README.md:
--------------------------------------------------------------------------------
1 | # Python实现支持向量机
2 | 使用Python实现支持向量机,代码思路来源于[机器学习实战](https://github.com/pbharrin/machinelearninginaction)。
3 |
4 | # 线性可分支持向量机
5 | 构建分类器,寻找一个超平面(hyperplane), 使得距离分割超平面最近的点和分割超平面的间隔(margin)尽可能远。使分类器尽可能健壮。支持向量(support vector)就是离分割超平面最近的那些点。
6 | 分割超平面的对应方程为**w****x**+b=0, 它由法向量**w**和截距b决定。点到超平面的距离为|**w****A**+b|/||**w**||。**w****x**表示**w**和**x**的内积。
7 |
8 | 计算数据点到分割面距离并确定分割面的放置位置, 间隔:label * (**w****x**+b)。label=1或-1。
9 |
10 | 最小间隔最大化:
11 |
12 | 
--------------------------------------------------------------------------------
/SVM/testSet.txt:
--------------------------------------------------------------------------------
1 | 3.542485 1.977398 -1
2 | 3.018896 2.556416 -1
3 | 7.551510 -1.580030 1
4 | 2.114999 -0.004466 -1
5 | 8.127113 1.274372 1
6 | 7.108772 -0.986906 1
7 | 8.610639 2.046708 1
8 | 2.326297 0.265213 -1
9 | 3.634009 1.730537 -1
10 | 0.341367 -0.894998 -1
11 | 3.125951 0.293251 -1
12 | 2.123252 -0.783563 -1
13 | 0.887835 -2.797792 -1
14 | 7.139979 -2.329896 1
15 | 1.696414 -1.212496 -1
16 | 8.117032 0.623493 1
17 | 8.497162 -0.266649 1
18 | 4.658191 3.507396 -1
19 | 8.197181 1.545132 1
20 | 1.208047 0.213100 -1
21 | 1.928486 -0.321870 -1
22 | 2.175808 -0.014527 -1
23 | 7.886608 0.461755 1
24 | 3.223038 -0.552392 -1
25 | 3.628502 2.190585 -1
26 | 7.407860 -0.121961 1
27 | 7.286357 0.251077 1
28 | 2.301095 -0.533988 -1
29 | -0.232542 -0.547690 -1
30 | 3.457096 -0.082216 -1
31 | 3.023938 -0.057392 -1
32 | 8.015003 0.885325 1
33 | 8.991748 0.923154 1
34 | 7.916831 -1.781735 1
35 | 7.616862 -0.217958 1
36 | 2.450939 0.744967 -1
37 | 7.270337 -2.507834 1
38 | 1.749721 -0.961902 -1
39 | 1.803111 -0.176349 -1
40 | 8.804461 3.044301 1
41 | 1.231257 -0.568573 -1
42 | 2.074915 1.410550 -1
43 | -0.743036 -1.736103 -1
44 | 3.536555 3.964960 -1
45 | 8.410143 0.025606 1
46 | 7.382988 -0.478764 1
47 | 6.960661 -0.245353 1
48 | 8.234460 0.701868 1
49 | 8.168618 -0.903835 1
50 | 1.534187 -0.622492 -1
51 | 9.229518 2.066088 1
52 | 7.886242 0.191813 1
53 | 2.893743 -1.643468 -1
54 | 1.870457 -1.040420 -1
55 | 5.286862 -2.358286 1
56 | 6.080573 0.418886 1
57 | 2.544314 1.714165 -1
58 | 6.016004 -3.753712 1
59 | 0.926310 -0.564359 -1
60 | 0.870296 -0.109952 -1
61 | 2.369345 1.375695 -1
62 | 1.363782 -0.254082 -1
63 | 7.279460 -0.189572 1
64 | 1.896005 0.515080 -1
65 | 8.102154 -0.603875 1
66 | 2.529893 0.662657 -1
67 | 1.963874 -0.365233 -1
68 | 8.132048 0.785914 1
69 | 8.245938 0.372366 1
70 | 6.543888 0.433164 1
71 | -0.236713 -5.766721 -1
72 | 8.112593 0.295839 1
73 | 9.803425 1.495167 1
74 | 1.497407 -0.552916 -1
75 | 1.336267 -1.632889 -1
76 | 9.205805 -0.586480 1
77 | 1.966279 -1.840439 -1
78 | 8.398012 1.584918 1
79 | 7.239953 -1.764292 1
80 | 7.556201 0.241185 1
81 | 9.015509 0.345019 1
82 | 8.266085 -0.230977 1
83 | 8.545620 2.788799 1
84 | 9.295969 1.346332 1
85 | 2.404234 0.570278 -1
86 | 2.037772 0.021919 -1
87 | 1.727631 -0.453143 -1
88 | 1.979395 -0.050773 -1
89 | 8.092288 -1.372433 1
90 | 1.667645 0.239204 -1
91 | 9.854303 1.365116 1
92 | 7.921057 -1.327587 1
93 | 8.500757 1.492372 1
94 | 1.339746 -0.291183 -1
95 | 3.107511 0.758367 -1
96 | 2.609525 0.902979 -1
97 | 3.263585 1.367898 -1
98 | 2.912122 -0.202359 -1
99 | 1.731786 0.589096 -1
100 | 2.387003 1.573131 -1
101 |
--------------------------------------------------------------------------------
/SelectionSort.py:
--------------------------------------------------------------------------------
1 | # 选择排序, 纯粹练手 - -||
2 | def selectionSort(alist):
3 | for i in range(len(alist)-1):
4 | min = i
5 | for j in range(i+1, len(alist)):
6 | if alist[j] < alist[min]:
7 | min = j
8 | alist[i], alist[min] = alist[min], alist[i]
9 | return alist
10 |
11 | alist = [54,26,93,17,77,31,44,55,20]
12 | print(selectionSort(alist))
--------------------------------------------------------------------------------
/ShellSort.py:
--------------------------------------------------------------------------------
1 | # python实现希尔排序
2 | def shellSort(alist):
3 | sublistcount= len(alist)//2
4 | while sublistcount > 0:
5 | for startposition in range(sublistcount):
6 | gapInsertionSort(alist, startposition, sublistcount)
7 | sublistcount = sublistcount//2
8 | return alist
9 |
10 | def gapInsertionSort(alist, start, gap):
11 | for i in range(start+gap, len(alist), gap):
12 | currentValue = alist[i]
13 | position = i
14 |
15 | while position >= gap and alist[position-gap] > currentValue:
16 | alist[position] = alist[position-gap]
17 | position = position-gap
18 | alist[position] = currentValue
19 |
20 | alist = [54,26,93,17,77,31,44,55,20]
21 | print(shellSort(alist))
--------------------------------------------------------------------------------
/Target Offer/README.md:
--------------------------------------------------------------------------------
1 | # Python实现《剑指offer》
2 |
3 | 部分代码自己添加了一些测试用例, 或者自己添加了一些功能
4 |
5 | 1. 初级程序员注重算法和数据结构
6 | 2. 事先做好准备,对工作有热情
7 | 3. 面试过程放松。不要急于写代码,了解清楚所要解决的问题,多和面试官沟通,然后开始做一些整体的设计和规划。不要急于提交,自己测试几个用例避免错误。
8 | 4. 良好的代码风格。命名规则,缩进对齐习惯。能够单元测试用例。
9 | 5. 项目介绍原则STAR:situation、task、action、result
10 | 6. 所需的素质:扎实的基础知识、能写高质量的代码、分析问题是思路清晰、能优化时间和空间效率、学习沟通能力
--------------------------------------------------------------------------------
/Target Offer/multiSparse.py:
--------------------------------------------------------------------------------
1 | '''
2 | 利用三元组完成稀疏矩阵相乘
3 | '''
4 |
5 | from numpy import *
6 | def sparseToTriple(matrix):
7 | m, n = shape(matrix)
8 | triple = []
9 | for i in range(m):
10 | for j in range(n):
11 | if matrix[i][j] != 0:
12 | triple.append([i, j, matrix[i][j]])
13 | return triple
14 |
15 | def multiTriple(tripleA, tripleB):
16 | rowA = shape(tripleA)[0]
17 | rowB = shape(tripleB)[0]
18 | multiMatrix = []
19 | for i in range(rowA):
20 | for j in range(rowB):
21 | if tripleA[i][1] == tripleB[j][0]:
22 | multiMatrix.append([tripleA[i][0], tripleB[j][1], tripleA[i][2]*tripleB[j][2]])
23 | return multiMatrix
24 |
25 | def tripleToSparse(triple, m, n):
26 | outMatrix = zeros([m, n])
27 | for pointTuple in triple:
28 | mLocation = pointTuple[0]
29 | nLocation = pointTuple[1]
30 | value = pointTuple[2]
31 | outMatrix[mLocation][nLocation] = value
32 | return outMatrix
33 |
34 | def matrixMultiple(matrixA, matrixB):
35 | mA, nA = shape(matrixA)
36 | mB, nB = shape(matrixB)
37 | if nA != mB:
38 | print("the two matries doesn't match!")
39 | return -1
40 |
41 | tripleA = sparseToTriple(matrixA)
42 | tripleB = sparseToTriple(matrixB)
43 | multiTriples = multiTriple(tripleA, tripleB)
44 | print(multiTriples)
45 | multiMatrix = tripleToSparse(multiTriples, mA, nB)
46 | return multiMatrix
47 |
48 | matrixA = [[3, 0, 0, 7],
49 | [0, 0, -1, 0],
50 | [-1, -2, 0, 0],
51 | [0, 0, 0, 2]]
52 | matrixB = [[0, 0, -2, 0, -1],
53 | [0, 0, -3, 0, 0],
54 | [-1, 0, 0, 0, 0],
55 | [0, 0, 0, 3, 0]]
56 | ans = matrixMultiple(matrixA, matrixB)
57 | print(ans)
--------------------------------------------------------------------------------
/Target Offer/n个骰子的点数.py:
--------------------------------------------------------------------------------
1 | # -*- coding:UTF-8 -*-
2 | '''
3 | 把n个骰子扔在地上, 所有骰子朝上一面的点数和为s。
4 | 输入n, 打印出s的所有可能的值出现的概率
5 | '''
6 | # 基于循环求点数, 时间性能好
7 | def PrintProbability(number):
8 | if number < 1:
9 | return
10 | maxVal = 6
11 | # 构造两个数组来存储骰子点数的每一个总数出现的次数
12 | # 在一次循环中, 第一个数组中的第n个数字表示骰子和为n出现的次数
13 | # 在下次循环中, 另一个数组的第n个数字设为前一个数组对应的第n-1、n-2、n-3、n-4、n-5、n-6之和
14 | probStorage = [[], []]
15 | probStorage[0] = [0]*(maxVal * number + 1)
16 | flag = 0
17 | for i in range(1, maxVal+1):
18 | probStorage[flag][i] = 1
19 | for time in range(2, number+1):
20 | probStorage[1-flag] = [0]*(maxVal * number + 1)
21 | for pCur in range(time, maxVal*time+1):
22 | diceNum = 1
23 | while diceNum < pCur and diceNum <= maxVal:
24 | probStorage[1-flag][pCur] += probStorage[flag][pCur-diceNum]
25 | diceNum += 1
26 | flag = 1 - flag
27 | total = maxVal ** number
28 | for i in range(number, maxVal*number+1):
29 | ratio = probStorage[flag][i] / float(total)
30 | print("{}: {:e}".format(i, ratio))
31 | s = PrintProbability(5)
--------------------------------------------------------------------------------
/Target Offer/transSparseMatrix.py:
--------------------------------------------------------------------------------
1 | '''
2 | 稀疏矩阵的转置
3 | 输入: 一个稀疏矩阵
4 | 输出: 矩阵的转置
5 | 方法: 中间可以利用三元组进行操作
6 | '''
7 | from numpy import *
8 | def sparseToTriple(matrix):
9 | m, n = shape(matrix)
10 | triple = []
11 | for i in range(m):
12 | for j in range(n):
13 | if matrix[i][j] != 0:
14 | triple.append([i, j, matrix[i][j]])
15 | return triple
16 |
17 | def transTriple(triple):
18 | m, n = shape(triple)
19 | transMatrix = []
20 | sortedIndex = array([m[1] for m in triple]).argsort()
21 | for i in range(m):
22 | tempArray = triple[sortedIndex[i]]
23 | transMatrix.append([tempArray[1], tempArray[0], tempArray[2]])
24 | return transMatrix
25 |
26 | def tripleToSparse(triple, m, n):
27 | outMatrix = zeros([n, m])
28 | for pointTuple in triple:
29 | mLocation = pointTuple[0]
30 | nLocation = pointTuple[1]
31 | value = pointTuple[2]
32 | outMatrix[mLocation][nLocation] = value
33 | return outMatrix
34 |
35 | def matrixTrans(matrix):
36 | m, n = shape(matrix)
37 | triple = sparseToTriple(matrix)
38 | transedTriple = transTriple(triple)
39 | transedMatrix = tripleToSparse(transedTriple, m, n)
40 | return transedMatrix
41 |
42 | matrix = [[0, 0, 0, 0, 0, 0, 6, 0, 0],
43 | [0, 0, 2, 0, 0, 1, 0, 0, 0],
44 | [0, 0, 0, 0, 0, 0, 0, 0, 0],
45 | [3, 0, 0, 0, 0, 0, 0, 0, 0],
46 | [0, 0, 0, 0, 0, 0, 0, 5, 0],
47 | [0, 7, 0, 0, 0, 0, 0, 0, 0],
48 | [0, 0, 0, 0, 0, 0, 0, 0, 8],
49 | [0, 0, 5, 0, 0, 0, 0, 0, 0],
50 | [0, 0, 0, 0, 0, 0, 0, 0, 0],
51 | [0, 0, 0, 2, 0, 0, 0, 0, 0]]
52 |
53 | transedMatrix = matrixTrans(matrix)
54 | print(transedMatrix)
--------------------------------------------------------------------------------
/Target Offer/不用加减乘除做加法.py:
--------------------------------------------------------------------------------
1 | '''
2 | 写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
3 | '''
4 | # 利用异或以及与进位求解
5 | # 不能一个正数一个负数
6 | # 可能是python的的整型可以无限大的原因, 导致正数和负数的异或操作不断变成更小的负数而不会溢出
7 | # 使用Swift尝试了一下, 还是可以求得正数和负数的位操作相加运算的
8 | # -*- coding:utf-8 -*-
9 | # class Solution:
10 | # def Add(self, num1, num2):
11 | # while num2:
12 | # sum = num1 ^ num2
13 | # carry = (num1 & num2) << 1
14 | # num1 = sum
15 | # num2 = carry
16 | # return num1
17 | # s = Solution()
18 | # print(s.Add(4, 2))
19 | # -*- coding:utf-8 -*-
20 | # 通过每次对num1进行与操作保证是一个32位的整形
21 | # 因此最后我们可以判断符号位是否为1做处理
22 | class Solution:
23 | def Add(self, num1, num2):
24 | # write code here
25 | while num2 != 0:
26 | temp = num1 ^ num2
27 | num2 = (num1 & num2) << 1
28 | num1 = temp & 0xFFFFFFFF
29 | return num1 if num1 >> 31 == 0 else num1 - 4294967296
30 |
--------------------------------------------------------------------------------
/Target Offer/丑数.py:
--------------------------------------------------------------------------------
1 | '''
2 | 把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。
3 | 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
4 | '''
5 |
6 | # -*- coding:utf-8 -*-
7 | class Solution:
8 | def GetUglyNumber_Solution(self, index):
9 | if index == None and len(index) <= 0:
10 | return 0
11 |
12 | uglyNumbers = [1]*index
13 | nextIndex = 1
14 |
15 | index2 = 0
16 | index3 = 0
17 | index5 = 0
18 |
19 | while nextIndex < index:
20 | minVal = min(uglyNumbers[index2]*2, uglyNumbers[index3]*3, uglyNumbers[index5]*5)
21 | uglyNumbers[nextIndex] = minVal
22 |
23 | while uglyNumbers[index2]*2 <= uglyNumbers[nextIndex]:
24 | index2 += 1
25 | while uglyNumbers[index3]*3 <= uglyNumbers[nextIndex]:
26 | index3 += 1
27 | while uglyNumbers[index5]*5 <= uglyNumbers[nextIndex]:
28 | index5 += 1
29 | nextIndex += 1
30 |
31 | return uglyNumbers[-1]
32 |
33 |
34 | s = Solution()
35 | print(s.GetUglyNumber_Solution(11))
36 |
37 | # def getUglyNumber(index):
38 | # if index <= 0:
39 | # return 0
40 | #
41 | # uglyNumbers = [1] * index
42 | # nextUglyIndex = 1
43 | #
44 | # index2 = 0
45 | # index3 = 0
46 | # index5 = 0
47 | # multiply2 = uglyNumbers[index2]
48 | # multiply3 = uglyNumbers[index3]
49 | # multiply5 = uglyNumbers[index5]
50 | #
51 | # while nextUglyIndex < index:
52 | # minVal = min(multiply2 * 2, multiply3 * 3, multiply5 * 5)
53 | # uglyNumbers[nextUglyIndex] = minVal
54 | #
55 | # while multiply2 * 2 <= uglyNumbers[nextUglyIndex]:
56 | # index2 += 1
57 | # multiply2 = uglyNumbers[index2]
58 | # while multiply3 * 3 <= uglyNumbers[nextUglyIndex]:
59 | # index3 += 1
60 | # multiply3 = uglyNumbers[index3]
61 | # while multiply5 * 5 <= uglyNumbers[nextUglyIndex]:
62 | # index5 += 1
63 | # multiply5 = uglyNumbers[index5]
64 | #
65 | # nextUglyIndex += 1
66 | # return uglyNumbers[-1]
--------------------------------------------------------------------------------
/Target Offer/两个链表的第一个公共结点.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入两个链表,找出它们的第一个公共结点。
3 | '''
4 |
5 | # -*- coding:utf-8 -*-
6 | class ListNode:
7 | def __init__(self, x):
8 | self.val = x
9 | self.next = None
10 | class Solution:
11 | def FindFirstCommonNode(self, pHead1, pHead2):
12 | nLength1 = self.GetListLength(pHead1)
13 | nLength2 = self.GetListLength(pHead2)
14 | nLengthDiff = abs(nLength1 - nLength2)
15 |
16 | if nLength1 > nLength2:
17 | pListHeadLong = pHead1
18 | pListHeadShort = pHead2
19 | else:
20 | pListHeadLong = pHead2
21 | pListHeadShort = pHead1
22 |
23 | for i in range(nLengthDiff):
24 | pListHeadLong = pListHeadLong.next
25 |
26 | while pListHeadLong != None and pListHeadShort != None and pListHeadLong != pListHeadShort:
27 | pListHeadLong = pListHeadLong.next
28 | pListHeadShort = pListHeadShort.next
29 |
30 | pFirstCommonNode = pListHeadLong
31 | return pFirstCommonNode
32 |
33 | def GetListLength(self, pHead):
34 | nLength = 0
35 | while pHead != None:
36 | pHead = pHead.next
37 | nLength += 1
38 | return nLength
--------------------------------------------------------------------------------
/Target Offer/二叉搜索树与双向链表.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。
3 | 要求不能创建任何新的结点,只能调整树中结点指针的指向。
4 | '''
5 |
6 | # -*- coding:utf-8 -*-
7 | class TreeNode:
8 | def __init__(self, x):
9 | self.val = x
10 | self.left = None
11 | self.right = None
12 | class Solution:
13 | def Convert(self, pRootOfTree):
14 | if pRootOfTree == None:
15 | return None
16 | if not pRootOfTree.left and not pRootOfTree.right:
17 | return pRootOfTree
18 |
19 | # 处理左子树
20 | self.Convert(pRootOfTree.left)
21 | left = pRootOfTree.left
22 |
23 | # 连接根与左子树最大结点
24 | if left:
25 | while left.right:
26 | left = left.right
27 | pRootOfTree.left, left.right = left, pRootOfTree
28 |
29 | # 处理右子树
30 | self.Convert(pRootOfTree.right)
31 | right = pRootOfTree.right
32 |
33 | # 连接根与右子树最小结点
34 | if right:
35 | while right.left:
36 | right = right.left
37 | pRootOfTree.right, right.left = right, pRootOfTree
38 |
39 | while pRootOfTree.left:
40 | pRootOfTree = pRootOfTree.left
41 |
42 | return pRootOfTree
43 |
44 | pNode1 = TreeNode(8)
45 | pNode2 = TreeNode(6)
46 | pNode3 = TreeNode(10)
47 | pNode4 = TreeNode(5)
48 | pNode5 = TreeNode(7)
49 | pNode6 = TreeNode(9)
50 | pNode7 = TreeNode(11)
51 |
52 | pNode1.left = pNode2
53 | pNode1.right = pNode3
54 | pNode2.left = pNode4
55 | pNode2.right = pNode5
56 | pNode3.left = pNode6
57 | pNode3.right = pNode7
58 |
59 | S = Solution()
60 | newList = S.Convert(pNode1)
61 | print(newList.val)
--------------------------------------------------------------------------------
/Target Offer/二叉搜索树的后续遍历序列.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。
3 | 如果是则输出Yes,否则输出No。
4 | 假设输入的数组的任意两个数字都互不相同。
5 | 二叉搜索树对于每一个非叶子节点, 均有结点左子节点<当前节点<结点右子节点
6 | '''
7 |
8 | # -*- coding:utf-8 -*-
9 | class Solution:
10 | def VerifySquenceOfBST(self, sequence):
11 | if sequence == []:
12 | return False
13 |
14 | root = sequence[-1]
15 | length = len(sequence)
16 | if min(sequence) > root or max(sequence) < root:
17 | return True
18 | index = 0
19 | # 二叉搜索树的左子树结点小于根节点
20 | '''
21 | 下面这个for循环特别需要主要index=i必须写在if语句外面,
22 | 否则就会发生当root结点前的所有元素小于root的时候, 正确判断应该为True,
23 | 但是因为if语句没有进入, index = 0 ,
24 | 在进入二叉搜索树的右子树结点大于根结点的for循环的时候, 因为sequence的数都小于root, 就会判断出错
25 | '''
26 | for i in range(length-1):
27 | index = i
28 | if sequence[i] > root:
29 | break
30 |
31 | # 二叉搜索树的右子树结点大于根结点
32 | # 这个循环中范围起始点必须是index+1, 不能为index
33 | # 因为当root结点前的所有元素小于root的时候,index=length-2,
34 | # 此时sequence[index]root, 所以从后面一个开始盘算右子树结点是否大于root, 也不会影响结果
36 | for j in range(index+1, length-1):
37 | if sequence[j] < root:
38 | return False
39 |
40 | left = True
41 | if index > 0:
42 | left = self.VerifySquenceOfBST(sequence[:index])
43 |
44 | right = True
45 | if index < length-1:
46 | right = self.VerifySquenceOfBST(sequence[index:length-1])
47 | return left and right
48 |
49 | array = [5, 7, 6, 9, 11, 10, 8]
50 | array2 = [4, 6, 7, 5]
51 | array3 = [1, 2, 3, 4, 5]
52 | S = Solution()
53 | print(S.VerifySquenceOfBST(array))
54 | print(S.VerifySquenceOfBST(array2))
55 | print(S.VerifySquenceOfBST(array3))
--------------------------------------------------------------------------------
/Target Offer/二叉搜索树的最低公共祖先.py:
--------------------------------------------------------------------------------
1 | '''
2 | 查找二叉搜索树两个结点的最低公共祖先
3 | '''
4 |
5 | # -*- coding:utf-8 -*-
6 | class TreeNode:
7 | def __init__(self, x):
8 | self.val = x
9 | self.left = None
10 | self.right = None
11 | class Solution:
12 | def findParent(self, pNode1, pNode2, root):
13 | if pNode1 == None or pNode2 == None:
14 | return
15 | if pNode1 == pNode2:
16 | return
17 | val1 = pNode1.val
18 | val2 = pNode2.val
19 | while root != None:
20 | if (val1 - root.val) * (val2 - root.val) <= 0:
21 | return root.val
22 | elif val1 > root.val and val2 > root.val:
23 | root = root.right
24 | else:
25 | root = root.left
26 |
27 | return False
28 |
29 | pNode1 = TreeNode(8)
30 | pNode2 = TreeNode(6)
31 | pNode3 = TreeNode(10)
32 | pNode4 = TreeNode(5)
33 | pNode5 = TreeNode(7)
34 | pNode6 = TreeNode(9)
35 | pNode7 = TreeNode(11)
36 |
37 | pNode1.left = pNode2
38 | pNode1.right = pNode3
39 | pNode2.left = pNode4
40 | pNode2.right = pNode5
41 | pNode3.left = pNode6
42 | pNode3.right = pNode7
43 |
44 | S = Solution()
45 | print(S.findParent(pNode3, pNode7, pNode1))
--------------------------------------------------------------------------------
/Target Offer/二叉搜索树的第k个结点.py:
--------------------------------------------------------------------------------
1 | '''
2 | 给定一颗二叉搜索树,请找出其中的第k大的结点。例如,
3 | 5
4 | / \
5 | 3 7
6 | /\ /\
7 | 2 4 6 8 中,
8 | 按结点数值大小顺序第三个结点的值为4。
9 | '''
10 |
11 | # -*- coding:utf-8 -*-
12 | class TreeNode:
13 | def __init__(self, x):
14 | self.val = x
15 | self.left = None
16 | self.right = None
17 | class Solution:
18 | # 返回对应节点TreeNode
19 | def __init__(self):
20 | self.treeNode = []
21 | def inOrder(self, pRoot):
22 | if len(self.treeNode) < 0:
23 | return None
24 | if pRoot.left:
25 | self.inOrder(pRoot.left)
26 | self.treeNode.append(pRoot)
27 | if pRoot.right:
28 | self.inOrder(pRoot.right)
29 | def KthNode(self, pRoot, k):
30 | if k == 0 or pRoot == None:
31 | return
32 | self.inOrder(pRoot)
33 | if len(self.treeNode) < k:
34 | return None
35 | return self.treeNode[k-1]
36 |
37 | def KthNode2(self, pRoot, k):
38 | if k <= 0 or not pRoot:
39 | return None
40 | treeStack, nodesQue = [], []
41 | pNode = pRoot
42 | while pNode or len(treeStack):
43 | while pNode:
44 | treeStack.append(pNode)
45 | pNode = pNode.left
46 | if len(treeStack):
47 | pNode = treeStack.pop()
48 | nodesQue.append(pNode)
49 | pNode = pNode.right
50 | if k > len(nodesQue):
51 | return None
52 | return nodesQue[k-1]
--------------------------------------------------------------------------------
/Target Offer/二叉树中和为某一值的路径.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。
3 | 路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。
4 | '''
5 | # -*- coding:utf-8 -*-
6 | class TreeNode:
7 | def __init__(self, x):
8 | self.val = x
9 | self.left = None
10 | self.right = None
11 | class Solution:
12 | # 返回二维列表,内部每个列表表示找到的路径
13 | def FindPath(self, root, sum):
14 | if not root:
15 | return []
16 | if root.left == None and root.right == None:
17 | if sum == root.val:
18 | return [[root.val]]
19 | else:
20 | return []
21 | stack = []
22 | leftStack = self.pathSum(root.left, sum - root.val)
23 | for i in leftStack:
24 | i.insert(0, root.val)
25 | stack.append(i)
26 | rightStack = self.pathSum(root.right, sum - root.val)
27 | for i in rightStack:
28 | i.insert(0, root.val)
29 | stack.append(i)
30 | return stack
31 |
32 | # 优化写法
33 | def pathSum(self, root, sum):
34 | if not root: return []
35 | if root.left == None and root.right == None:
36 | if sum == root.val:
37 | return [[root.val]]
38 | else:
39 | return []
40 | a = self.pathSum(root.left, sum - root.val) + self.pathSum(root.right, sum - root.val)
41 | return [[root.val] + i for i in a]
42 |
43 | pNode1 = TreeNode(10)
44 | pNode2 = TreeNode(5)
45 | pNode3 = TreeNode(12)
46 | pNode4 = TreeNode(4)
47 | pNode5 = TreeNode(7)
48 |
49 |
50 | pNode1.left = pNode2
51 | pNode1.right = pNode3
52 | pNode2.left = pNode4
53 | pNode2.right = pNode5
54 |
55 |
56 | S = Solution()
57 | print(S.FindPath(pNode1, 22))
58 | # 测试用例:[1,-2,-3,1,3,-2,null,-1] -1
59 | # 测试用例:[-2, None, -3] -5
--------------------------------------------------------------------------------
/Target Offer/二叉树的下一个结点.py:
--------------------------------------------------------------------------------
1 | '''
2 | 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。
3 | 注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
4 | '''
5 | # -*- coding:utf-8 -*-
6 | class TreeLinkNode:
7 | def __init__(self, x):
8 | self.val = x
9 | self.left = None
10 | self.right = None
11 | self.next = None
12 | class Solution:
13 | def GetNext(self, pNode):
14 | if pNode == None:
15 | return
16 | pNext = None
17 | if pNode.right != None:
18 | pRight = pNode.right
19 | while pRight.left != None:
20 | pRight = pRight.left
21 | pNext= pRight
22 | elif pNode.next != None:
23 | pCurrent = pNode
24 | pParent = pCurrent.next
25 | while pParent != None and pCurrent == pParent.right:
26 | pCurrent = pParent
27 | pParent = pCurrent.next
28 | pNext = pParent
29 | return pNext
30 |
31 | class Solution2:
32 | def GetNext(self, pNode):
33 | # 输入是一个空节点
34 | if pNode == None:
35 | return None
36 | # 注意当前节点是根节点的情况。所以在最开始设定pNext = None, 如果下列情况都不满足, 说明当前结点为根节点, 直接输出None
37 | pNext = None
38 | # 如果输入节点有右子树,则下一个结点是当前节点右子树中最左节点
39 | if pNode.right:
40 | pNode = pNode.right
41 | while pNode.left:
42 | pNode = pNode.left
43 | pNext = pNode
44 | else:
45 | # 如果当前节点有父节点且当前节点是父节点的左子节点, 下一个结点即为父节点
46 | if pNode.next and pNode.next.left == pNode:
47 | pNext = pNode.next
48 | # 如果当前节点有父节点且当前节点是父节点的右子节点, 那么向上遍历
49 | # 当遍历到当前节点为父节点的左子节点时, 输入节点的下一个结点为当前节点的父节点
50 | elif pNode.next and pNode.next.right == pNode:
51 | pNode = pNode.next
52 | while pNode.next and pNode.next.right == pNode:
53 | pNode = pNode.next
54 | # 遍历终止时当前节点有父节点, 说明当前节点是父节点的左子节点, 输入节点的下一个结点为当前节点的父节点
55 | # 反之终止时当前节点没有父节点, 说明当前节点在位于根节点的右子树, 没有下一个结点
56 | if pNode.next:
57 | pNext = pNode.next
58 | return pNext
--------------------------------------------------------------------------------
/Target Offer/二叉树的最低公共祖先.py:
--------------------------------------------------------------------------------
1 | # 二叉树的最低公共祖先
2 | """
3 | Definition of TreeNode:
4 | """
5 | class TreeNode:
6 | def __init__(self, val):
7 | self.val = val
8 | self.left, self.right = None, None
9 | class Solution:
10 | """
11 | @param root: The root of the binary search tree.
12 | @param A and B: two nodes in a Binary.
13 | @return: Return the least common ancestor(LCA) of the two nodes.
14 | """
15 |
16 | def lowestCommonAncestor(self, root, A, B):
17 | # write your code here
18 | if root == None:
19 | return False
20 | pathA = self.storeNodes(root, A)[0]
21 | pathB = self.storeNodes(root, B)[0]
22 | if pathA and pathB:
23 | lenA, lenB = len(pathA), len(pathB)
24 | diff = abs(lenA - lenB)
25 | if lenA > lenB:
26 | markA = lenA - diff - 1
27 | markB = lenB - 1
28 | else:
29 | markA = lenA - 1
30 | markB = lenB - diff - 1
31 | while markA >= 0 and markB >= 0:
32 | if pathA[markA] == pathB[markB]:
33 | return pathA[markA]
34 | markA -= 1
35 | markB -= 1
36 |
37 | def storeNodes(self, root, targetNode):
38 | if root == None or targetNode == None:
39 | return []
40 | elif root.val == targetNode.val:
41 | return [[targetNode]]
42 | stack = []
43 | if root.left:
44 | stackLeft = self.storeNodes(root.left, targetNode)
45 | for i in stackLeft:
46 | i.insert(0, root)
47 | stack.append(i)
48 | if root.right:
49 | stackRight = self.storeNodes(root.right, targetNode)
50 | for i in stackRight:
51 | i.insert(0, root)
52 | stack.append(i)
53 | return stack
54 |
55 |
--------------------------------------------------------------------------------
/Target Offer/二叉树的深度.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入一棵二叉树,求该树的深度。
3 | 从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
4 | '''
5 |
6 | # -*- coding:utf-8 -*-
7 | class TreeNode:
8 | def __init__(self, x):
9 | self.val = x
10 | self.left = None
11 | self.right = None
12 | class Solution:
13 | # 递归解法, 简单直接, 时间复杂度O(n), 空间复杂度O(logn)
14 | def TreeDepth(self, pRoot):
15 | if pRoot == None:
16 | return 0
17 | else:
18 | return max(self.TreeDepth(pRoot.left), self.TreeDepth(pRoot.right)) + 1
19 | # 非递归算法,利用一个栈以及一个标志位栈
20 | def TreeDepth2(self, pRoot):
21 | if not pRoot:
22 | return 0
23 | depth = 0
24 | stack, tag = [], []
25 | pNode = pRoot
26 | while pNode or stack:
27 | while pNode:
28 | stack.append(pNode)
29 | tag.append(0)
30 | pNode = pNode.left
31 | if tag[-1] == 1:
32 | depth = max(depth, len(stack))
33 | stack.pop()
34 | tag.pop()
35 | pNode = None
36 | else:
37 | pNode = stack[-1]
38 | pNode = pNode.right
39 | tag.pop()
40 | tag.append(1)
41 | return depth
--------------------------------------------------------------------------------
/Target Offer/二叉树的镜像.py:
--------------------------------------------------------------------------------
1 | '''
2 | 操作给定的二叉树,将其变换为源二叉树的镜像。
3 | '''
4 |
5 | # -*- coding:utf-8 -*-
6 | class TreeNode:
7 | def __init__(self, x):
8 | self.val = x
9 | self.left = None
10 | self.right = None
11 | class Solution:
12 | # 递归实现
13 | def Mirror(self, root):
14 | if root == None:
15 | return
16 | if root.left == None and root.right == None:
17 | return root
18 |
19 | pTemp = root.left
20 | root.left = root.right
21 | root.right = pTemp
22 |
23 | self.Mirror(root.left)
24 | self.Mirror(root.right)
25 |
26 | # 非递归实现
27 | def Mirror2(self, root):
28 | if root == None:
29 | return
30 | stackNode = []
31 | stackNode.append(root)
32 | while len(stackNode) > 0:
33 | nodeNum = len(stackNode) - 1
34 | tree = stackNode[nodeNum]
35 | stackNode.pop()
36 | nodeNum -= 1
37 | if tree.left != None or tree.right != None:
38 | tree.left, tree.right = tree.right, tree.left
39 | if tree.left:
40 | stackNode.append(tree.left)
41 | nodeNum += 1
42 | if tree.right:
43 | stackNode.append(tree.right)
44 | nodeNum += 1
45 | # 非递归实现
46 | def MirrorNoRecursion(self, root):
47 | if root == None:
48 | return
49 | nodeQue = [root]
50 | while len(nodeQue) > 0:
51 | curLevel, count = len(nodeQue), 0
52 | while count < curLevel:
53 | count += 1
54 | pRoot = nodeQue.pop(0)
55 | pRoot.left, pRoot.right = pRoot.right, pRoot.left
56 | if pRoot.left:
57 | nodeQue.append(pRoot.left)
58 | if pRoot.right:
59 | nodeQue.append(pRoot.right)
60 |
61 | pNode1 = TreeNode(8)
62 | pNode2 = TreeNode(6)
63 | pNode3 = TreeNode(10)
64 | pNode4 = TreeNode(5)
65 | pNode5 = TreeNode(7)
66 | pNode6 = TreeNode(9)
67 | pNode7 = TreeNode(11)
68 |
69 | pNode1.left = pNode2
70 | pNode1.right = pNode3
71 | pNode2.left = pNode4
72 | pNode2.right = pNode5
73 | pNode3.left = pNode6
74 | pNode3.right = pNode7
75 |
76 | S = Solution()
77 | S.Mirror2(pNode1)
78 | print(pNode1.right.left.val)
--------------------------------------------------------------------------------
/Target Offer/二进制中1的个数.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
3 | '''
4 |
5 | class Solution:
6 | def NumberOf1(self, n):
7 | count = 0
8 | if n < 0:
9 | n = n & 0xffffffff
10 | while n:
11 | count += 1
12 | n = (n-1)&n
13 | return count
14 |
15 | def NumberOf2(self, n):
16 | if n < 0:
17 | s = bin(n & 0xffffffff)
18 | else:
19 | s = bin(n)
20 | return s.count('1')
21 |
22 | # 判断一个数是不是2得整数次幂
23 | def powerOf2(self, n):
24 | if n&(n-1) == 0:
25 | return True
26 | else:
27 | return False
28 | # 判断两个数的二进制表示有多少位不一样, 直接比较两个数的二进制异或就可以
29 | def andOr(self, m, n):
30 | diff = m^n
31 | count = 0
32 | while diff:
33 | count += 1
34 | diff = diff&(diff-1)
35 | return count
36 |
37 | S = Solution()
38 | print(S.NumberOf1(-1))
39 | print(S.NumberOf2(-1))
40 | print(S.powerOf2(64))
41 | print(S.powerOf2(63))
42 | print(S.andOr(10, 13))
--------------------------------------------------------------------------------
/Target Offer/从上往下打印二叉树.py:
--------------------------------------------------------------------------------
1 | '''
2 | 从上往下打印出二叉树的每个节点,同层节点从左至右打印。
3 | '''
4 |
5 | '''
6 | 相当于按层遍历, 中间需要队列做转存
7 | '''
8 |
9 | # -*- coding:utf-8 -*-
10 | class TreeNode:
11 | def __init__(self, x):
12 | self.val = x
13 | self.left = None
14 | self.right = None
15 | class Solution:
16 | # 返回从上到下每个节点值列表,例:[1,2,3]
17 | def PrintFromTopToBottom(self, root):
18 | queue = []
19 | if not root:
20 | return []
21 |
22 | result = []
23 | queue.append(root)
24 | while len(queue) > 0:
25 | currentRoot = queue.pop(0)
26 | result.append(currentRoot.val)
27 | if currentRoot.left:
28 | queue.append(currentRoot.left)
29 | if currentRoot.right:
30 | queue.append(currentRoot.right)
31 | return result
32 |
33 | pNode1 = TreeNode(8)
34 | pNode2 = TreeNode(6)
35 | pNode3 = TreeNode(10)
36 | pNode4 = TreeNode(5)
37 | pNode5 = TreeNode(7)
38 | pNode6 = TreeNode(9)
39 | pNode7 = TreeNode(11)
40 |
41 | pNode1.left = pNode2
42 | pNode1.right = pNode3
43 | pNode2.left = pNode4
44 | pNode2.right = pNode5
45 | pNode3.left = pNode6
46 | pNode3.right = pNode7
47 |
48 | S = Solution()
49 | print(S.PrintFromTopToBottom(pNode1))
--------------------------------------------------------------------------------
/Target Offer/八皇后问题.py:
--------------------------------------------------------------------------------
1 | '''
2 | 在8*8的国际象棋上摆放八个皇后, 使其不能相互攻击, 即任意两个皇后不得处在同一行, 同一列或者同一对角线上
3 | '''
4 |
5 | '''
6 | 可以用回溯法, 也可以用下面的判别方法:
7 | 由于8各皇后的任意两个不能处在同一行, 那么肯定每一个皇后占据一行。
8 | 定义一个数组columnIndex[8], 数组中的第i个数字表示位于第i行的皇后列号
9 | 先把数组columnIndex[8]的8个数字分别用0-7初始化, 接下来就是对数组columnIndex的全排列
10 | 因为我们使用不同的数字初始化数组,所以任意两个皇后肯定不同列, 只需判断每一个排列对应的8个皇后是不是在一个对角线上
11 | 也就是对于下标i和j, 是不是abs(i-j) = columnIndex[i]-columnIndex[j]
12 | '''
13 |
14 | class Solution:
15 | # 全排列出所有顶点组合
16 | def Permutation(self, pointArr):
17 | if not len(pointArr):
18 | return []
19 | if len(pointArr) == 1:
20 | return pointArr
21 | numList = pointArr
22 | numList.sort()
23 | pStr = []
24 | for i in range(len(numList)):
25 | if i > 0 and numList[i] == numList[i-1]:
26 | continue
27 | temp = self.Permutation(numList[:i] + numList[i+1:])
28 | if type(temp[0]) == int:
29 | for j in temp:
30 | pStr.append([numList[i]] + [j])
31 | else:
32 | for j in temp:
33 | tempArr = [numList[i]] + j
34 | pStr.append(tempArr)
35 | return pStr
36 |
37 | def Judge(self, alist):
38 | length = len(alist)
39 | for i in range(length):
40 | for j in range(length):
41 | if i == j:
42 | continue
43 | if i - j == alist[i] - alist[j] or j - i == alist[i] - alist[j]:
44 | return False
45 | return True
46 |
47 | def queen(self, alist):
48 | allAns = self.Permutation(alist)
49 | for tempList in allAns:
50 | isQueen = self.Judge(tempList)
51 | if isQueen:
52 | print(tempList)
53 |
54 |
55 | s = Solution()
56 | s.queen([0, 1, 2, 3, 4, 5, 6, 7])
--------------------------------------------------------------------------------
/Target Offer/删除链表中重复的结点.py:
--------------------------------------------------------------------------------
1 | '''
2 | 删除链表中重复的结点
3 | 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。
4 | 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
5 | '''
6 |
7 | # -*- coding:utf-8 -*-
8 | class ListNode:
9 | def __init__(self, x):
10 | self.val = x
11 | self.next = None
12 | class Solution:
13 | def deleteDuplication(self, pHead):
14 | if pHead == None:
15 | return
16 | preHead = None
17 | pNode = pHead
18 | while pNode != None:
19 | needDelete = False
20 | nextNode = pNode.next
21 | if nextNode != None and nextNode.val == pNode.val:
22 | needDelete = True
23 | if needDelete == False:
24 | preHead = pNode
25 | pNode = pNode.next
26 | else:
27 | nodeVal = pNode.val
28 | pToBeDel = pNode
29 | while pToBeDel != None and pToBeDel.val == nodeVal:
30 | pToBeDel = pToBeDel.next
31 | if preHead == None:
32 | pHead = pToBeDel
33 | pNode = pToBeDel
34 | continue
35 | else:
36 | preHead.next = pToBeDel
37 | pNode = preHead
38 | return pHead
39 |
40 | node1 = ListNode(1)
41 | node2 = ListNode(2)
42 | node3 = ListNode(3)
43 | node4 = ListNode(3)
44 | node5 = ListNode(4)
45 | node6 = ListNode(4)
46 | node7 = ListNode(5)
47 | node1.next = node2
48 | node2.next = node3
49 | node3.next = node4
50 | node4.next = node5
51 | node5.next = node6
52 | node6.next = node7
53 |
54 | s = Solution()
55 | print(s.deleteDuplication(node1).next.next.val)
--------------------------------------------------------------------------------
/Target Offer/判断平衡二叉树.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入一棵二叉树,判断该二叉树是否是平衡二叉树。
3 | '''
4 |
5 | # -*- coding:utf-8 -*-
6 | class TreeNode:
7 | def __init__(self, x):
8 | self.val = x
9 | self.left = None
10 | self.right = None
11 | class Solution:
12 | def __init__(self):
13 | self.flag = True
14 |
15 | def IsBalanced_Solution(self, pRoot):
16 | self.getDepth(pRoot)
17 | return self.flag
18 |
19 | def getDepth(self, pRoot):
20 | if pRoot == None:
21 | return 0
22 | left = 1 + self.getDepth(pRoot.left)
23 | right = 1 + self.getDepth(pRoot.right)
24 |
25 | if abs(left - right) > 1:
26 | self.flag = False
27 |
28 | return left if left > right else right
29 | class Solution2:
30 | def getDepth(self, pRoot):
31 | if pRoot == None:
32 | return 0
33 | return max(self.getDepth(pRoot.left), self.getDepth(pRoot.right)) + 1
34 | def IsBalanced_Solution(self, pRoot):
35 | if pRoot == None:
36 | return True
37 | if abs(self.getDepth(pRoot.left)-self.getDepth(pRoot.right)) > 1:
38 | return False
39 | return self.IsBalanced_Solution(pRoot.left) and self.IsBalanced_Solution(pRoot.right)
40 |
41 |
42 | pNode1 = TreeNode(1)
43 | pNode2 = TreeNode(2)
44 | pNode3 = TreeNode(3)
45 | pNode4 = TreeNode(4)
46 | pNode5 = TreeNode(5)
47 | pNode6 = TreeNode(6)
48 | pNode7 = TreeNode(7)
49 |
50 | pNode1.left = pNode2
51 | pNode1.right = pNode3
52 | pNode2.left = pNode4
53 | pNode2.right = pNode5
54 | pNode3.right = pNode6
55 | pNode5.left = pNode7
56 |
57 | S = Solution2()
58 | print(S.getDepth(pNode1))
--------------------------------------------------------------------------------
/Target Offer/包含min函数的栈.py:
--------------------------------------------------------------------------------
1 | '''
2 | 定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。
3 | '''
4 |
5 | # -*- coding:utf-8 -*-
6 | class Solution:
7 | def __init__(self):
8 | self.stack = []
9 | self.minStack = []
10 | def push(self, node):
11 | self.stack.append(node)
12 | if self.minStack == [] or node < self.min():
13 | self.minStack.append(node)
14 | else:
15 | temp = self.min()
16 | self.minStack.append(temp)
17 |
18 | def pop(self):
19 | if self.stack == [] or self.minStack == []:
20 | return None
21 | self.minStack.pop()
22 | self.stack.pop()
23 |
24 | def top(self):
25 | return self.stack[-1]
26 | def min(self):
27 | return self.minStack[-1]
28 |
29 | S = Solution()
30 | S.push(3)
31 | S.push(4)
32 | S.push(2)
33 | S.push(1)
34 | print(S.min())
35 | S.pop()
36 | print(S.min())
37 | S.pop()
38 | print(S.min())
--------------------------------------------------------------------------------
/Target Offer/反向打印链表.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入一个链表,从尾到头打印链表每个节点的值。
3 | '''
4 | class ListNode:
5 | def __init__(self, x=None):
6 | self.val = x
7 | self.next = None
8 |
9 | class Solution:
10 | def printListFromTailToHead(self, listNode):
11 | if listNode.val == None:
12 | return
13 | l = []
14 | head = listNode
15 | while head:
16 | l.insert(0, head.val)
17 | head = head.next
18 | return l
19 |
20 | node1 = ListNode(10)
21 | node2 = ListNode(11)
22 | node3 = ListNode(13)
23 | node1.next = node2
24 | node2.next = node3
25 |
26 | singleNode = ListNode(12)
27 |
28 | test = ListNode()
29 |
30 | S = Solution()
31 | print(S.printListFromTailToHead(node1))
32 | print(S.printListFromTailToHead(test))
33 | print(S.printListFromTailToHead(singleNode))
34 |
--------------------------------------------------------------------------------
/Target Offer/反转链表.py:
--------------------------------------------------------------------------------
1 | '''
2 | 反转链表
3 | 输入一个链表,反转链表后,输出链表的所有元素
4 | '''
5 |
6 | # -*- coding:utf-8 -*-
7 | class ListNode:
8 | def __init__(self, x):
9 | self.val = x
10 | self.next = None
11 | class Solution:
12 | # 返回ListNode
13 | def ReverseList(self, pHead):
14 | pReversedHead = None
15 | pNode = pHead
16 | pPrev = None
17 | while pNode != None:
18 | pNext = pNode.next
19 |
20 | if pNext == None:
21 | pReversedHead = pNode
22 |
23 | pNode.next = pPrev
24 | pPrev = pNode
25 | pNode = pNext
26 | return pReversedHead
27 | # 递归实现反转链表
28 | def ReverseListRec(self, pHead):
29 | if not pHead or not pHead.next:
30 | return pHead
31 | else:
32 | pReversedHead = self.ReverseList(pHead.next)
33 | pHead.next.next = pHead
34 | pHead.next = None
35 | return pReversedHead
36 |
37 | node1 = ListNode(10)
38 | node2 = ListNode(11)
39 | node3 = ListNode(13)
40 | node1.next = node2
41 | node2.next = node3
42 |
43 | S = Solution()
44 | p = S.ReverseList(node1)
45 | print(p.next.val)
--------------------------------------------------------------------------------
/Target Offer/句子中单词首字母大写.py:
--------------------------------------------------------------------------------
1 | '''
2 | 面试题:
3 | 一个句子的所有单词的首字母大写,其余小写
4 | '''
5 | def title(s):
6 | if not s:
7 | return ""
8 | res = ""
9 | diff = ord("a") - ord("A")
10 | for i in range(1, len(s)):
11 | if s[i-1] == " " and s[i] <= "z" and s[i] >= "a":
12 | res += chr(ord(s[i]) - diff)
13 | elif s[i-1] != " " and s[i] <= "Z" and s[i] >= "A":
14 | res += chr(ord(s[i]) + diff)
15 | else:
16 | res += s[i]
17 | if s[0] <= "z" and s[0] >= "a":
18 | res = chr(ord(s[0]) - diff) + res
19 | else:
20 | res = s[0] + res
21 | return res
22 |
23 | def title2(s):
24 | return s.title()
25 |
26 | print(title2(" sDsa sddr jki "))
--------------------------------------------------------------------------------
/Target Offer/合并两个排序的链表.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
3 | '''
4 |
5 | class ListNode:
6 | def __init__(self, x):
7 | self.val = x
8 | self.next = None
9 | class Solution:
10 | # 返回合并后列表
11 | def Merge(self, pHead1, pHead2):
12 | if pHead1 == None:
13 | return pHead2
14 | elif pHead2 == None:
15 | return pHead1
16 |
17 | pMergedHead = None
18 | if pHead1.val < pHead2.val:
19 | pMergedHead = pHead1
20 | pMergedHead.next = self.Merge(pHead1.next, pHead2)
21 | else:
22 | pMergedHead = pHead2
23 | pMergedHead.next = self.Merge(pHead1, pHead2.next)
24 |
25 | return pMergedHead
26 |
27 | node1 = ListNode(1)
28 | node2 = ListNode(3)
29 | node3 = ListNode(5)
30 | node1.next = node2
31 | node2.next = node3
32 |
33 | node4 = ListNode(2)
34 | node5 = ListNode(4)
35 | node6 = ListNode(6)
36 | node4.next = node5
37 | node5.next = node6
38 |
39 | S = Solution()
40 | S.Merge(node1, node4)
41 | print(node4.next.val)
--------------------------------------------------------------------------------
/Target Offer/和为s的两个数字.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,
3 | 如果有多对数字的和等于S,输出两个数的乘积最小的。
4 | 对应每个测试案例,输出两个数,小的先输出。
5 | '''
6 |
7 | # -*- coding:utf-8 -*-
8 | class Solution:
9 | # 从左右一起查找
10 | # 因为当两个数的和一定的时候, 两个数字的间隔越大, 乘积越小
11 | # 所以直接输出查找到的第一对数即可
12 | def FindNumbersWithSum(self, array, tsum):
13 | if array == None or len(array) <= 0 or array[-1] + array[-2] < tsum:
14 | return []
15 | start = 0
16 | end = len(array)-1
17 | while start < end:
18 | sum = array[start] + array[end]
19 |
20 | if sum < tsum:
21 | start += 1
22 | elif sum > tsum:
23 | end -= 1
24 | else:
25 | return [array[start], array[end]]
26 | return []
27 |
28 | test = [1,2,4,7,11,15]
29 | s = Solution()
30 | print(s.FindNumbersWithSum(test, 15))
--------------------------------------------------------------------------------
/Target Offer/和为s的连续整数序列.py:
--------------------------------------------------------------------------------
1 | '''
2 | 找出所有和为S的连续正数序列
3 | 输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
4 | '''
5 | class Solution:
6 | def FindContinuousSequence(self, tsum):
7 | if tsum < 3:
8 | return []
9 | small = 1
10 | big = 2
11 | middle = (tsum + 1) // 2
12 | curSum = small + big
13 | output = []
14 | while small < middle:
15 | if curSum == tsum:
16 | output.append(list(range(small, big+1)))
17 | while curSum > tsum and small < middle:
18 | curSum -= small
19 | small += 1
20 | if curSum == tsum:
21 | output.append(list(range(small, big+1)))
22 | big += 1
23 | curSum += big
24 | return output
25 |
26 | def FindContinuousSequence2(self, tsum):
27 | if tsum < 3:
28 | return []
29 | small, big = 1, 2
30 | middle = (tsum + 1) >> 1
31 | curSum = small + big
32 | output = []
33 | while small < middle:
34 | if curSum == tsum:
35 | output.append(list(range(small, big + 1)))
36 | big += 1
37 | curSum += big
38 | elif curSum > tsum:
39 | curSum -= small
40 | small += 1
41 | else:
42 | big += 1
43 | curSum += big
44 | return output
45 | s = Solution()
46 | print(s.FindContinuousSequence2(15))
--------------------------------------------------------------------------------
/Target Offer/在O(1)时间内删除链表结点.py:
--------------------------------------------------------------------------------
1 | '''
2 | 给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点
3 | '''
4 | class ListNode:
5 | def __init__(self, x=None):
6 | self.val = x
7 | self.next = None
8 | def __del__(self):
9 | self.val = None
10 | self.next = None
11 |
12 | class Solution:
13 | def DeleteNode(self, pListHead, pToBeDeleted):
14 | if not pListHead or not pToBeDeleted:
15 | return None
16 |
17 | if pToBeDeleted.next != None:
18 | pNext = pToBeDeleted.next
19 | pToBeDeleted.val = pNext.val
20 | pToBeDeleted.next = pNext.next
21 | pNext.__del__()
22 |
23 |
24 | elif pListHead == pToBeDeleted:
25 | pToBeDeleted.__del__()
26 | pListHead.__del__()
27 | else:
28 | pNode = pListHead
29 | while pNode.next != pToBeDeleted:
30 | pNode = pNode.next
31 | pNode.next = None
32 | pToBeDeleted.__del__()
33 |
34 |
35 | node1 = ListNode(10)
36 | node2 = ListNode(11)
37 | node3 = ListNode(13)
38 | node4 = ListNode(15)
39 | node1.next = node2
40 | node2.next = node3
41 | node3.next = node4
42 |
43 | S = Solution()
44 | S.DeleteNode(node1, node3)
45 | print(node3.val)
46 | S.DeleteNode(node1, node3)
47 | print(node3.val)
48 | print(node2.val)
49 | S.DeleteNode(node1, node1)
50 | print(node1.val)
51 | S.DeleteNode(node1, node1)
52 | print(node1.val)
53 |
--------------------------------------------------------------------------------
/Target Offer/复杂链表的复制.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入一个复杂链表(每个节点中有节点值,以及两个指针,
3 | 一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。
4 | '''
5 |
6 | # -*- coding:utf-8 -*-
7 | class RandomListNode:
8 | def __init__(self, x):
9 | self.label = x
10 | self.next = None
11 | self.random = None
12 | class Solution:
13 | # 返回 RandomListNode
14 | def Clone(self, pHead):
15 | if pHead == None:
16 | return None
17 | self.CloneNodes(pHead)
18 | self.ConnectRandomNodes(pHead)
19 | return self.ReconnectNodes(pHead)
20 | # 复制原始链表的每个结点, 将复制的结点链接在其原始结点的后面
21 | def CloneNodes(self, pHead):
22 | pNode = pHead
23 | while pNode:
24 | pCloned = RandomListNode(0)
25 | pCloned.label = pNode.label
26 | pCloned.next = pNode.next
27 | # pCloned.random = None #不需要写这句话, 因为创建新的结点的时候,random自动指向None
28 |
29 | pNode.next = pCloned
30 | pNode = pCloned.next
31 |
32 | # 将复制后的链表中的复制结点的random指针链接到被复制结点random指针的后一个结点
33 | def ConnectRandomNodes(self, pHead):
34 | pNode = pHead
35 | while pNode:
36 | pCloned = pNode.next
37 | if pNode.random != None:
38 | pCloned.random = pNode.random.next
39 | pNode = pCloned.next
40 |
41 | # 拆分链表, 将原始链表的结点组成新的链表, 复制结点组成复制后的链表
42 | def ReconnectNodes(self, pHead):
43 | pNode = pHead
44 | pClonedHead = pClonedNode = pNode.next
45 | pNode.next = pClonedHead.next
46 | pNode = pNode.next
47 |
48 | while pNode:
49 | pClonedNode.next = pNode.next
50 | pClonedNode = pClonedNode.next
51 | pNode.next = pClonedNode.next
52 | pNode = pNode.next
53 |
54 | return pClonedHead
55 |
56 | node1 = RandomListNode(1)
57 | node2 = RandomListNode(3)
58 | node3 = RandomListNode(5)
59 | node1.next = node2
60 | node2.next = node3
61 | node1.random = node3
62 |
63 | S = Solution()
64 | clonedNode = S.Clone(node1)
65 | print(clonedNode.random.label)
--------------------------------------------------------------------------------
/Target Offer/字符串具有相同字符的最长子串.py:
--------------------------------------------------------------------------------
1 | '''
2 | 求一个字符串的最长子串,其中子串所有字符相同
3 | 面试题
4 | '''
5 | def findCommonLCS(s):
6 | if not s:
7 | return ""
8 | if len(s) == 1:
9 | return s
10 | length = len(s)
11 | maxIndex, maxLength = 0, 1
12 | curIndex = 0
13 | while curIndex < length:
14 | tempLength = 1
15 | while curIndex + tempLength < length and s[curIndex] == s[curIndex+tempLength]:
16 | tempLength += 1
17 | if maxLength < tempLength:
18 | maxLength = tempLength
19 | maxIndex = curIndex
20 | if curIndex + tempLength == length:
21 | break
22 | curIndex += tempLength
23 | if maxLength == 1:
24 | return s[0]
25 | else:
26 | res = s[maxIndex:maxIndex+maxLength]
27 | return res
28 |
29 | print(findCommonLCS("abbbasagsagsgdsaagaaccagcfsccccc"))
--------------------------------------------------------------------------------
/Target Offer/字符串的左旋转.py:
--------------------------------------------------------------------------------
1 | '''
2 | 汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。
3 | 对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。
4 | 例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。
5 | '''
6 |
7 | # -*- coding:utf-8 -*-
8 | class Solution:
9 | def LeftRotateString(self, s, n):
10 | if len(s) <= 0 or len(s) < n or n < 0:
11 | return ''
12 | strList= list(s)
13 | self.Reverse(strList)
14 | length = len(s)
15 | pivot = length - n
16 | frontList = self.Reverse(strList[:pivot])
17 | behindList = self.Reverse(strList[pivot:])
18 | resultStr = ''.join(frontList) + ''.join(behindList)
19 | return resultStr
20 |
21 | def Reverse(self, alist):
22 | if alist == None or len(alist) <= 0:
23 | return ''
24 | startIndex = 0
25 | endIndex = len(alist) - 1
26 | while startIndex < endIndex:
27 | alist[startIndex], alist[endIndex] = alist[endIndex], alist[startIndex]
28 | startIndex += 1
29 | endIndex -= 1
30 | return alist
31 |
32 | test = 'abcdefg'
33 | s = Solution()
34 | print(s.LeftRotateString(test, 2))
--------------------------------------------------------------------------------
/Target Offer/字符串的排列和组合.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入一个字符串,按字典序打印出该字符串中字符的所有排列。
3 | 例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
4 | 结果请按字母顺序输出。
5 | 输入描述:
6 | 输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
7 | '''
8 |
9 | # -*- coding:utf-8 -*-
10 | class Solution:
11 | def Permutation(self, ss):
12 | if not len(ss):
13 | return []
14 | if len(ss) == 1:
15 | return list(ss)
16 |
17 | charList = list(ss)
18 | charList.sort()
19 | pStr = []
20 | for i in range(len(charList)):
21 | if i > 0 and charList[i] == charList[i-1]:
22 | continue
23 | temp = self.Permutation(''.join(charList[:i])+''.join(charList[i+1:]))
24 | for j in temp:
25 | pStr.append(charList[i]+j)
26 | return pStr
27 |
28 | # 扩展习题, 生成字符的所有组合
29 | # 比如输入abc, 则他们的组合有['a', 'ab', 'abc', 'ac', 'b', 'bc', 'c'], ab和ba属于不同的排列, 但属于同一个组合
30 | def group(self, ss):
31 | if not len(ss):
32 | return []
33 | if len(ss) == 1:
34 | return list(ss)
35 | charList = list(ss)
36 | charList.sort()
37 | pStr = []
38 | for i in range(len(charList)):
39 | pStr.append(charList[i])
40 | if i > 0 and charList[i] == charList[i - 1]:
41 | continue
42 | temp = self.group(''.join(charList[i + 1:]))
43 | for j in temp:
44 | pStr.append(charList[i] + j)
45 | pStr = list(set(pStr))
46 | pStr.sort()
47 | return pStr
48 |
49 | ss = 'acb'
50 | S = Solution()
51 | # print(S.Permutation(ss))
52 | print(S.group(ss))
--------------------------------------------------------------------------------
/Target Offer/字符流中第一个不重复的字符.py:
--------------------------------------------------------------------------------
1 | '''
2 | 请实现一个函数用来找出字符流中第一个只出现一次的字符。
3 | 例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。
4 | 当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
5 | 如果当前字符流没有存在出现一次的字符,返回#字符。
6 | '''
7 |
8 | # -*- coding:utf-8 -*-
9 | class Solution:
10 | def __init__(self):
11 | self.adict = {}
12 | self.alist = []
13 | def FirstAppearingOnce(self):
14 | while len(self.alist) > 0 and self.adict[self.alist[0]] == 2:
15 | self.alist.pop(0)
16 | if len(self.alist) == 0:
17 | return '#'
18 | else:
19 | return self.alist[0]
20 | def Insert(self, char):
21 | if char not in self.adict.keys():
22 | self.adict[char] = 1
23 | self.alist.append(char)
24 | elif self.adict[char]:
25 | self.adict[char] = 2
--------------------------------------------------------------------------------
/Target Offer/对称的二叉树.py:
--------------------------------------------------------------------------------
1 | '''
2 | 请实现一个函数,用来判断一颗二叉树是不是对称的。
3 | 注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
4 | '''
5 |
6 | # -*- coding:utf-8 -*-
7 | class TreeNode:
8 | def __init__(self, x):
9 | self.val = x
10 | self.left = None
11 | self.right = None
12 | class Solution:
13 | def isSymmetrical(self, pRoot):
14 | return self.selfIsSymmetrical(pRoot, pRoot)
15 | def selfIsSymmetrical(self, pRoot1, pRoot2):
16 | if pRoot1 == None and pRoot2 == None:
17 | return True
18 | if pRoot1 == None or pRoot2 == None:
19 | return False
20 | if pRoot1.val != pRoot2.val:
21 | return False
22 | return self.selfIsSymmetrical(pRoot1.left, pRoot2.right) and self.selfIsSymmetrical(pRoot1.right, pRoot2.left)
23 | # 非递归实现判断二叉树是否对称
24 | # 利用前序遍历
25 | class Solution2:
26 | def isSymmetrical(self, pRoot):
27 | preList = self.preOrder(pRoot)
28 | mirrorList = self.mirrorPreOrder(pRoot)
29 | if preList == mirrorList:
30 | return True
31 | return False
32 |
33 | def preOrder(self, pRoot):
34 | if pRoot == None:
35 | return [None]
36 | treeStack = []
37 | output = []
38 | pNode = pRoot
39 | while pNode or len(treeStack) > 0:
40 | while pNode:
41 | treeStack.append(pNode)
42 | output.append(pNode.val)
43 | pNode = pNode.left
44 | if not pNode:
45 | output.append(None)
46 | if len(treeStack):
47 | pNode = treeStack.pop()
48 | pNode = pNode.right
49 | if not pNode:
50 | output.append(None)
51 | return output
52 |
53 | def mirrorPreOrder(self, pRoot):
54 | if pRoot == None:
55 | return [None]
56 | treeStack = []
57 | output = []
58 | pNode = pRoot
59 | while pNode or len(treeStack) > 0:
60 | while pNode:
61 | treeStack.append(pNode)
62 | output.append(pNode.val)
63 | pNode = pNode.right
64 | if not pNode:
65 | output.append(None)
66 | if len(treeStack):
67 | pNode = treeStack.pop()
68 | pNode = pNode.left
69 | if not pNode:
70 | output.append(None)
71 | return output
72 |
73 | pNode1 = TreeNode(8)
74 | pNode2 = TreeNode(6)
75 | pNode3 = TreeNode(10)
76 | pNode4 = TreeNode(5)
77 | pNode5 = TreeNode(7)
78 | pNode6 = TreeNode(9)
79 | pNode7 = TreeNode(11)
80 |
81 | pNode1.left = pNode2
82 | pNode1.right = pNode3
83 | pNode2.left = pNode4
84 | pNode2.right = pNode5
85 | pNode3.left = pNode6
86 | pNode3.right = pNode7
87 |
88 | S = Solution2()
89 | result = S.isSymmetrical(pNode1)
90 | print(result)
--------------------------------------------------------------------------------
/Target Offer/带锁的门.py:
--------------------------------------------------------------------------------
1 | '''
2 | 走廊上有n个带锁的门,从1到n依次编号。最初所有的门都是关着的。我们从门前经过n次,每次都是从1号门开始。
3 | 在第i次经过的时候改变第i个整数倍号所的状态。
4 | 在最后一次经过的后, 哪些门是打开的, 输出打开门的序号
5 | '''
6 |
7 | def openDoor(n):
8 | if n == None or n <= 0:
9 | return
10 | doorList = [0] * (n+1)
11 | for i in range(1, len(doorList)):
12 | j = i
13 | while j <= n:
14 | doorList[j] = 1 - doorList[j]
15 | j += i
16 | output = [i for i, x in enumerate(doorList) if x != 0]
17 | return output
18 |
19 | print(openDoor(16))
20 |
--------------------------------------------------------------------------------
/Target Offer/序列化二叉树.py:
--------------------------------------------------------------------------------
1 | '''
2 | 请实现两个函数,分别用来序列化和反序列化二叉树。这里没有规定序列化的方式。
3 | '''
4 |
5 | # -*- coding:utf-8 -*-
6 | class TreeNode:
7 | def __init__(self, x):
8 | self.val = x
9 | self.left = None
10 | self.right = None
11 | class Solution:
12 | def Serialize(self, root):
13 | serializeStr = ''
14 | if root == None:
15 | return '#'
16 | stack = []
17 | while root or stack:
18 | while root:
19 | serializeStr += str(root.val) + ','
20 | stack.append(root)
21 | root = root.left
22 | serializeStr += '#,'
23 | root = stack.pop()
24 | root = root.right
25 | serializeStr = serializeStr[:-1]
26 | return serializeStr
27 |
28 | def Deserialize(self, s):
29 | serialize = s.split(',')
30 | tree, sp = self.deserialize(serialize, 0)
31 | return tree
32 |
33 | def deserialize(self, s, sp):
34 | if sp >= len(s) or s[sp] == '#':
35 | return None, sp + 1
36 | node = TreeNode(int(s[sp]))
37 | sp += 1
38 | node.left, sp = self.deserialize(s, sp)
39 | node.right, sp = self.deserialize(s, sp)
40 | return node, sp
--------------------------------------------------------------------------------
/Target Offer/扑克牌的顺子.py:
--------------------------------------------------------------------------------
1 | '''
2 | 随机从扑克牌中抽出了5张牌,判断是不是顺子,
3 | 决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。
4 | '''
5 |
6 | # -*- coding:utf-8 -*-
7 | class Solution:
8 | def IsContinuous(self, numbers):
9 | if numbers == None or len(numbers) <= 0:
10 | return False
11 | # 把A、J、Q、K转化一下
12 | transDict = {'A': 1, 'J': 11, 'Q': 12, 'K': 13}
13 | for i in range(len(numbers)):
14 | if numbers[i] in transDict.keys():
15 | numbers[i] = transDict[numbers[i]]
16 |
17 | numbers = sorted(numbers)
18 | numberOfzero = 0
19 | numberOfGap = 0
20 |
21 | # 统计0的个数
22 | i = 0
23 | while i < len(numbers) and numbers[i] == 0:
24 | numberOfzero += 1
25 | i += 1
26 | # 统计间隔的数目
27 | small = numberOfzero
28 | big = small + 1
29 | while big < len(numbers):
30 | # 出现对子, 不可能是顺子
31 | if numbers[small] == numbers[big]:
32 | return False
33 |
34 | numberOfGap += numbers[big] - numbers[small] - 1
35 | small = big
36 | big += 1
37 | return False if numberOfGap > numberOfzero else True
38 |
39 | test = ['A', 3, 2, 5, 0]
40 | test2 = [0, 3, 1, 6, 4]
41 | s = Solution()
42 | print(s.IsContinuous(test2))
--------------------------------------------------------------------------------
/Target Offer/打印1到最大的n位数.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入数字n, 按顺序打印从1最大的n位十进制数
3 | 比如输入3, 则打印出1、2、3、到最大的3位数即999
4 | '''
5 |
6 | def Print1ToMaxOfNDigits(n):
7 | if n <= 0:
8 | return
9 |
10 | number = ['0'] * n
11 | while not Increment(number):
12 | PrintNumber(number)
13 |
14 | def Increment(number):
15 | isOverflow = False
16 | nTakeOver = 0
17 | nLength = len(number)
18 |
19 | for i in range(nLength-1, -1, -1):
20 | nSum = int(number[i]) + nTakeOver
21 | if i == nLength - 1:
22 | nSum += 1
23 |
24 | if nSum >= 10:
25 | if i == 0:
26 | isOverflow = True
27 | else:
28 | nSum -= 10
29 | nTakeOver = 1
30 | number[i] = str(nSum)
31 | else:
32 | number[i] = str(nSum)
33 | break
34 |
35 | return isOverflow
36 |
37 | def PrintNumber(number):
38 | isBeginning0 = True
39 | nLength = len(number)
40 |
41 | for i in range(nLength):
42 | if isBeginning0 and number[i] != '0':
43 | isBeginning0 = False
44 | if not isBeginning0:
45 | print('%c' % number[i], end='')
46 | print('')
47 | #
48 | # Print1ToMaxOfNDigits(2)
49 |
50 | def Print1ToMaxOfNDigits2(n):
51 | if n <= 0:
52 | return
53 |
54 | number = ['0'] * n
55 | for i in range(10):
56 | number[0] = str(i)
57 | Print1ToMaxOfNDigitsRecursively(number, n, 0)
58 |
59 | def Print1ToMaxOfNDigitsRecursively(number, length, index):
60 | if index == length - 1:
61 | PrintNumber(number)
62 | return
63 | for i in range(10):
64 | number[index + 1] = str(i)
65 | Print1ToMaxOfNDigitsRecursively(number, length, index+1)
66 |
67 | Print1ToMaxOfNDigits2(2)
--------------------------------------------------------------------------------
/Target Offer/找出字符串中重复出现的最长子串.py:
--------------------------------------------------------------------------------
1 | '''
2 | 找出一行字符串中出现的相同且长度最长的字符串, 输出它及首字符的位置
3 | 例如"yyabcdabjcabceg", 输出结果应该为abc和3
4 | '''
5 |
6 | def maxStr(string):
7 | if string == None or len(string) <= 0:
8 | return
9 | if len(string) == 1:
10 | return [string, 0]
11 | length = len(string)
12 | temp = []
13 | for i in range(length):
14 | temp.append(string[i:])
15 | listWithIndex = []
16 | for index, val in enumerate(temp):
17 | listWithIndex.append([val, index+1])
18 | listWithIndex.sort()
19 | maxLength, maxList, maxIndex = 0, "", 0
20 | for listIndex in range(length-1):
21 | firstList = listWithIndex[listIndex]
22 | secondList = listWithIndex[listIndex+1]
23 | index, tempLength, tempList = 0, 0, ""
24 | while index < len(firstList[0]) and index < len(secondList[0]) and firstList[0][index] == secondList[0][index]:
25 | tempLength += 1
26 | tempList += firstList[0][index]
27 | index += 1
28 | if tempLength > maxLength:
29 | maxLength = tempLength
30 | maxList = tempList
31 | maxIndex = min(firstList[1], secondList[1])
32 | return [maxList, maxIndex]
33 |
34 |
35 |
36 |
37 | print(maxStr("yyabcdabjcabceg"))
38 | print(maxStr("abcbc"))
--------------------------------------------------------------------------------
/Target Offer/把二叉树打印成多行.py:
--------------------------------------------------------------------------------
1 | '''
2 | 从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
3 | '''
4 |
5 | # -*- coding:utf-8 -*-
6 | class TreeNode:
7 | def __init__(self, x):
8 | self.val = x
9 | self.left = None
10 | self.right = None
11 | class Solution:
12 | # 返回二维列表[[1,2],[4,5]]
13 | def levelOrder(self, pRoot):
14 | if pRoot == None:
15 | return []
16 | nodes, res = [pRoot], []
17 | while nodes:
18 | curStack, nextStack = [], []
19 | for node in nodes:
20 | curStack.append(node.val)
21 | if node.left:
22 | nextStack.append(node.left)
23 | if node.right:
24 | nextStack.append(node.right)
25 | res.append(curStack)
26 | nodes = nextStack
27 | return res
28 |
29 |
30 | pNode1 = TreeNode(8)
31 | pNode2 = TreeNode(6)
32 | pNode3 = TreeNode(10)
33 | pNode4 = TreeNode(5)
34 | pNode5 = TreeNode(7)
35 | pNode6 = TreeNode(9)
36 | pNode7 = TreeNode(11)
37 |
38 | pNode1.left = pNode2
39 | pNode1.right = pNode3
40 | pNode2.left = pNode4
41 | pNode2.right = pNode5
42 | pNode3.left = pNode6
43 | pNode3.right = pNode7
44 |
45 | S = Solution()
46 | aList = S.Print(pNode1)
47 | print(aList)
--------------------------------------------------------------------------------
/Target Offer/把字符串转换成整数.py:
--------------------------------------------------------------------------------
1 | '''
2 | 将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数
3 | '''
4 |
5 | # -*- coding:utf-8 -*-
6 | class Solution:
7 | # 如果输出是0, 通过检查flag判断输入不合法还是输入直接是'0'
8 | def StrToInt(self, s):
9 | flag = False
10 | if s == None or len(s) < 1:
11 | return 0
12 | numStack = []
13 | dict = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
14 | for i in s:
15 | if i in dict.keys():
16 | numStack.append(dict[i])
17 | elif i == '+':
18 | continue
19 | elif i == '-':
20 | continue
21 | else:
22 | return 0
23 | print(numStack)
24 | ans = 0
25 | if len(numStack) == 1 and numStack[0] == 0:
26 | flag = True
27 | return 0
28 | for i in numStack:
29 | ans = ans*10 + i
30 | if s[0] == '-':
31 | ans = 0 - ans
32 | return ans
33 |
34 | test = '-123-56'
35 | s = Solution()
36 | print(s.StrToInt(test))
--------------------------------------------------------------------------------
/Target Offer/把数组排成最小的数.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
3 | 例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
4 | '''
5 | # 运行环境Python 3.x
6 | from functools import cmp_to_key
7 | # -*- coding:utf-8 -*-
8 | class Solution:
9 | def PrintMinNumber(self, numbers):
10 | if numbers == None or len(numbers) <= 0:
11 | return ''
12 | strList = []
13 | for i in numbers:
14 | strList.append(str(i))
15 | # key是一种比较规则
16 | # 比较 x+y 和 x-y 的大小, 因为为str型, 需要先转换成int型
17 | key = cmp_to_key(lambda x, y: int(x+y)-int(y+x))
18 | strList.sort(key=key)
19 | return ''.join(strList)
20 | # 使用冒泡排序
21 | def PrintMinNumber2(self, numbers):
22 | if numbers == None or len(numbers) <= 0:
23 | return ''
24 | strNum = [str(m) for m in numbers]
25 | for i in range(len(numbers)-1):
26 | for j in range(i+1, len(numbers)):
27 | if strNum[i] + strNum[j] > strNum[j] + strNum[i]:
28 | strNum[i], strNum[j] = strNum[j], strNum[i]
29 | return ''.join(strNum)
30 |
31 | numbers = [3, 32, 321]
32 | s = Solution()
33 | print(s.PrintMinNumber(numbers))
34 |
35 | # 运行环境 Python 2.7
36 |
37 | # class Solution:
38 | # def PrintMinNumber(self, numbers):
39 | # # write code here
40 | # if numbers == None or len(numbers) == 0:
41 | # return ""
42 | # A = ["" for i in range(len(numbers))]
43 | # for i in range(len(numbers)):
44 | # A[i] = str(numbers[i])
45 | # A.sort(self.cmp)
46 | # return "".join(A)
47 | # def cmp(self,e1,e2):
48 | # s1 =e1+e2
49 | # s2 = e2 + e1
50 | # return cmp(s1,s2)
51 |
--------------------------------------------------------------------------------
/Target Offer/按之字形顺序打印二叉树.py:
--------------------------------------------------------------------------------
1 | '''
2 | 请实现一个函数按照之字形打印二叉树,
3 | 即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
4 | '''
5 |
6 | # -*- coding:utf-8 -*-
7 | class TreeNode:
8 | def __init__(self, x):
9 | self.val = x
10 | self.left = None
11 | self.right = None
12 | class Solution:
13 | # 存储点的时候按照奇数层和偶数层分别存储
14 | def Print(self, pRoot):
15 | if not pRoot:
16 | return []
17 | result, nodes = [], [pRoot]
18 | right = True
19 | while nodes:
20 | curStack, nextStack = [], []
21 | if right:
22 | for node in nodes:
23 | curStack.append(node.val)
24 | if node.left:
25 | nextStack.append(node.left)
26 | if node.right:
27 | nextStack.append(node.right)
28 | else:
29 | for node in nodes:
30 | curStack.append(node.val)
31 | if node.right:
32 | nextStack.append(node.right)
33 | if node.left:
34 | nextStack.append(node.left)
35 | nextStack.reverse()
36 | right = not right
37 | result.append(curStack)
38 | nodes = nextStack
39 | return result
40 | # 转换思路,存储的时候一直从左向右存储,打印的时候根据不同的层一次打印
41 | def zigzagLevelOrder(self, root):
42 | if not root:
43 | return []
44 | levels, result, leftToRight = [root], [], True
45 | while levels:
46 | curValues, nextLevel = [], []
47 | for node in levels:
48 | curValues.append(node.val)
49 | if node.left:
50 | nextLevel.append(node.left)
51 | if node.right:
52 | nextLevel.append(node.right)
53 | if not leftToRight:
54 | curValues.reverse()
55 | if curValues:
56 | result.append(curValues)
57 | levels = nextLevel
58 | leftToRight = not leftToRight
59 | return result
60 |
61 |
62 | pNode1 = TreeNode(8)
63 | pNode2 = TreeNode(6)
64 | pNode3 = TreeNode(10)
65 | pNode4 = TreeNode(5)
66 | pNode5 = TreeNode(7)
67 | pNode6 = TreeNode(9)
68 | pNode7 = TreeNode(11)
69 |
70 | pNode1.left = pNode2
71 | pNode1.right = pNode3
72 | pNode2.left = pNode4
73 | pNode2.right = pNode5
74 | pNode3.left = pNode6
75 | pNode3.right = pNode7
76 |
77 | S = Solution()
78 | aList = S.Print(pNode1)
79 | print(aList)
--------------------------------------------------------------------------------
/Target Offer/数值的整数次方.py:
--------------------------------------------------------------------------------
1 | '''
2 | 给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
3 | '''
4 |
5 | '''
6 | 需要注意的地方:
7 | 当指数为负数的时候
8 | 当底数为零切指数为负数的情况
9 | 在判断底数base是不是等于0的时候,不能直接写base==0, 因为计算机内表示小数时有误差,只能判断他们的差的绝对值是不是在一个很小的范围内
10 | '''
11 |
12 | '''
13 | 当n为偶数, a^n = a^(n/2) * a^(n/2)
14 | 当n为奇数, a^n = a^((n-1)/2) * a^((n-1)/2)) * a
15 | 利用右移一位运算代替除以2
16 | 利用位与运算代替了求余运算法%来判断一个数是奇数还是偶数
17 | 优化代码速度
18 | '''
19 | class Solution:
20 | def Power(self, base, exponent):
21 | if exponent == 0:
22 | return 1
23 | if exponent == 1:
24 | return base
25 | if exponent == -1:
26 | return 1/base
27 |
28 | result = self.Power(base, exponent >> 1)
29 | result *= result
30 | if (exponent & 0x1) == 1:
31 | result *= base
32 | return result
33 |
34 | S = Solution()
35 | print(S.Power(5, -10))
--------------------------------------------------------------------------------
/Target Offer/数字在排序数组中出现的次数.py:
--------------------------------------------------------------------------------
1 | '''
2 | 统计一个数字在排序数组中出现的次数。
3 | '''
4 |
5 | # -*- coding:utf-8 -*-
6 | class Solution:
7 | def GetNumberOfK(self, data, k):
8 | number = 0
9 | if data != None and len(data) > 0:
10 | length = len(data)
11 | first = self.GetFirstK(data, length, k, 0, length-1)
12 | last = self.GetLastK(data, length, k, 0, length-1)
13 | if first > -1:
14 | number = last - first + 1
15 | return number
16 |
17 | def GetFirstK(self, data, length, k, start, end):
18 | if start > end:
19 | return -1
20 |
21 | middleIndex = (start + end) // 2
22 | middleData = data[middleIndex]
23 |
24 | if middleData == k:
25 | if middleIndex > 0 and data[middleIndex-1] == k:
26 | end = middleIndex - 1
27 | else:
28 | return middleIndex
29 | elif middleData > k:
30 | end = middleIndex - 1
31 | else:
32 | start = middleIndex + 1
33 | return self.GetFirstK(data, length, k, start, end)
34 |
35 | def GetLastK(self, data, length, k, start, end):
36 | if start > end:
37 | return -1
38 |
39 | middleIndex = (start + end) // 2
40 | middleData = data[middleIndex]
41 |
42 | if middleData == k:
43 | if middleIndex < end and data[middleIndex+1] == k:
44 | start = middleIndex + 1
45 | else:
46 | return middleIndex
47 | elif middleData > k:
48 | end = middleIndex - 1
49 | else:
50 | start = middleIndex + 1
51 | return self.GetLastK(data, length, k, start, end)
52 |
53 | alist = [3,3,3,3,4,5]
54 | s = Solution()
55 | print(s.GetNumberOfK(alist, 3))
--------------------------------------------------------------------------------
/Target Offer/数据流中的中位数.py:
--------------------------------------------------------------------------------
1 | '''
2 | 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。
3 | 如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
4 | '''
5 |
6 | # -*- coding:utf-8 -*-
7 | class Solution:
8 | def __init__(self):
9 | self.left = []
10 | self.right = []
11 | self.count = 0
12 | def Insert(self, num):
13 | if self.count & 1 == 0:
14 | self.left.append(num)
15 | else:
16 | self.right.append(num)
17 | self.count += 1
18 |
19 | def GetMedian(self, x):
20 | if self.count == 1:
21 | return self.left[0]
22 | self.MaxHeap(self.left)
23 | self.MinHeap(self.right)
24 | if self.left[0] > self.right[0]:
25 | self.left[0], self.right[0] = self.right[0], self.left[0]
26 | self.MaxHeap(self.left)
27 | self.MinHeap(self.right)
28 | if self.count & 1 == 0:
29 | return (self.left[0] + self.right[0])/2.0
30 | else:
31 | return self.left[0]
32 |
33 | def MaxHeap(self, alist):
34 | length = len(alist)
35 | if alist == None or length <= 0:
36 | return
37 | if length == 1:
38 | return alist
39 | for i in range(length//2-1, -1, -1):
40 | k = i; temp = alist[k]; heap = False
41 | while not heap and 2*k < length-1:
42 | index = 2*k+1
43 | if index < length - 1:
44 | if alist[index] < alist[index + 1]: index += 1
45 | if temp >= alist[index]: heap = True
46 | else:
47 | alist[k] = alist[index]
48 | k = index
49 | alist[k] = temp
50 |
51 | def MinHeap(self, alist):
52 | length = len(alist)
53 | if alist == None or length <= 0:
54 | return
55 | if length == 1:
56 | return alist
57 | for i in range(length//2-1, -1, -1):
58 | k = i; temp = alist[k]; heap = False
59 | while not heap and 2 * k < length - 1:
60 | index = 2 * k+1
61 | if index < length - 1:
62 | if alist[index] > alist[index + 1]: index += 1
63 | if temp <= alist[index]:
64 | heap = True
65 | else:
66 | alist[k] = alist[index]
67 | k = index
68 | alist[k] = temp
69 |
--------------------------------------------------------------------------------
/Target Offer/数组中只出现一次的数字.py:
--------------------------------------------------------------------------------
1 | '''
2 | 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
3 | '''
4 |
5 | # -*- coding:utf-8 -*-
6 | class Solution:
7 | # 返回[a,b] 其中ab是出现一次的两个数字
8 | def FindNumsAppearOnce(self, array):
9 | if array == None or len(array) <= 0:
10 | return []
11 | resultExclusiveOr = 0
12 | for i in array:
13 | resultExclusiveOr ^= i
14 |
15 | indexOf1 = self.FindFirstBitIs1(resultExclusiveOr)
16 | num1, num2 = 0
17 | for j in range(len(array)):
18 | if self.IsBit1(array[j], indexOf1):
19 | num1 ^= array[j]
20 | else:
21 | num2 ^= array[j]
22 | return [num1, num2]
23 |
24 | def FindFirstBitIs1(self, num):
25 | indexBit = 0
26 | while num & 1 == 0 and indexBit <= 32:
27 | indexBit += 1
28 | num = num >> 1
29 | return indexBit
30 |
31 | def IsBit1(self, num, indexBit):
32 | num = num >> indexBit
33 | return num & 1
34 |
35 | class Solution2:
36 | # 返回[a,b] 其中ab是出现一次的两个数字
37 | def FindNumsAppearOnce(self, array):
38 | if array == None or len(array) <= 0:
39 | return []
40 | resultExOr = self.ExOr(array)
41 | i = 0
42 | while resultExOr and i <= 32:
43 | i += 1
44 | resultExOr = resultExOr>>1
45 | num1, num2 = [], []
46 | for num in array:
47 | if self.bitIs1(num, i):
48 | num1.append(num)
49 | else:
50 | num2.append(num)
51 | first = self.ExOr(num1)
52 | second = self.ExOr(num2)
53 | return [first, second]
54 |
55 | def ExOr(self, aList):
56 | ExOrNum = 0
57 | for i in aList:
58 | ExOrNum = ExOrNum ^ i
59 | return ExOrNum
60 | def bitIs1(self, n, i):
61 | n = n >> (i-1)
62 | return n & 1
63 |
64 | aList = [2, 4, 3, 6, 3, 2, 5, 5]
65 | s = Solution()
66 | print(s.FindNumsAppearOnce(aList))
--------------------------------------------------------------------------------
/Target Offer/数组中的逆序对.py:
--------------------------------------------------------------------------------
1 | '''
2 | 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。
3 | 输入一个数组,求出这个数组中的逆序对的总数P。
4 | '''
5 |
6 | # -*- coding:utf-8 -*-
7 | class Solution:
8 | def InversePairs(self, data):
9 | length = len(data)
10 | if data == None or length <= 0:
11 | return 0
12 | copy = [0]*length
13 | for i in range(length):
14 | copy[i] = data[i]
15 |
16 | count = self.InversePairsCore(data, copy, 0, length-1)
17 | return count
18 | def InversePairsCore(self, data, copy, start, end):
19 | if start == end:
20 | copy[start] = data[start]
21 | return 0
22 | length = (end - start)//2
23 | left = self.InversePairsCore(copy, data, start, start+length)
24 | right = self.InversePairsCore(copy, data, start+length+1, end)
25 |
26 | # i初始化为前半段最后一个数字的下标
27 | i = start + length
28 | # j初始化为后半段最后一个数字的下标
29 | j = end
30 |
31 | indexCopy = end
32 | count = 0
33 | while i >= start and j >= start+length+1:
34 | if data[i] > data[j]:
35 | copy[indexCopy] = data[i]
36 | indexCopy -= 1
37 | i -= 1
38 | count += j - start - length
39 | else:
40 | copy[indexCopy] = data[j]
41 | indexCopy -= 1
42 | j -= 1
43 |
44 | while i >= start:
45 | copy[indexCopy] = data[i]
46 | indexCopy -= 1
47 | i -= 1
48 | while j >= start+length+1:
49 | copy[indexCopy] = data[j]
50 | indexCopy -= 1
51 | j -= 1
52 | return left + right + count
53 |
54 | # 使用数据的index进行求解
55 | def InversePairs2(self, data):
56 | if len(data) <= 0:
57 | return 0
58 | count = 0
59 | copy = []
60 | for i in range(len(data)):
61 | copy.append(data[i])
62 | copy.sort()
63 | i = 0
64 | while len(copy) > i:
65 | count += data.index(copy[i])
66 | data.remove(copy[i])
67 | i += 1
68 | return count
69 |
70 | s = Solution()
71 | print(s.InversePairs2([364,637,341,406,747,995,234,971,571,219,993,407,416,366,315,301,601,650,418,355,460,505,360,965,516,648,727,667,465,849,455,181,486,149,588,233,144,174,557,67,746,550,474,162,268,142,463,221,882,576,604,739,288,569,256,936,275,401,497,82,935,983,583,523,697,478,147,795,380,973,958,115,773,870,259,655,446,863,735,784,3,671,433,630,425,930,64,266,235,187,284,665,874,80,45,848,38,811,267,575]))
--------------------------------------------------------------------------------
/Target Offer/数组中重复的数字.py:
--------------------------------------------------------------------------------
1 | '''
2 | 在一个长度为n的数组里的所有数字都在0到n-1的范围内。
3 | 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。
4 | 请找出数组中任意一个重复的数字。
5 | 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3。
6 | '''
7 |
8 | # -*- coding:utf-8 -*-
9 | class Solution:
10 | # 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
11 | # 函数返回True/False
12 | def duplicate(self, numbers, duplication):
13 | if numbers == None or len(numbers) <= 0:
14 | return False
15 | for i in numbers:
16 | if i < 0 or i > len(numbers) - 1:
17 | return False
18 | for i in range(len(numbers)):
19 | while numbers[i] != i:
20 | if numbers[i] == numbers[numbers[i]]:
21 | duplication[0] = numbers[i]
22 | return True
23 | else:
24 | index = numbers[i]
25 | numbers[i], numbers[index] = numbers[index], numbers[i]
26 | return False
27 | # 输出所有重复的数字
28 | def duplicate2(self, numbers):
29 | if numbers == None or len(numbers) <= 0:
30 | return False
31 | for i in numbers:
32 | if i < 0 or i > len(numbers) - 1:
33 | return False
34 | repeatedNums = []
35 | for i in range(len(numbers)):
36 | while numbers[i] != i:
37 | if numbers[i] == numbers[numbers[i]]:
38 | repeatedNums.append(numbers[i])
39 | break
40 | else:
41 | index = numbers[i]
42 | numbers[i], numbers[index] = numbers[index], numbers[i]
43 | return repeatedNums
44 |
45 | test = [2, 3, 1, 0, 2, 5, 3]
46 | s = Solution()
47 | dupulication = [0]
48 | print(s.duplicate(test,dupulication))
49 | print(s.duplicate2(test))
--------------------------------------------------------------------------------
/Target Offer/整数中1出现的次数.py:
--------------------------------------------------------------------------------
1 | '''
2 | 求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?
3 | 1~13中包含1的数字有1、10、11、12、13因此共出现6次。
4 | '''
5 |
6 | # -*- coding:utf-8 -*-
7 | class Solution:
8 | def NumberOf1Between1AndN_Solution(self, n):
9 | ones, m = 0, 1
10 | while m <= n:
11 | ones += (n // m + 8) // 10 * m + (n // m % 10 == 1) * (n % m + 1)
12 | m *= 10
13 | return ones
14 |
15 | def NumberOf1Between1AndN2(self, n):
16 | ones, m = 0, 1
17 | while m <= n:
18 | if ((n // m) % 10) != 0 and ((n // m) % 10) != 1:
19 | ones += (n // 10 // m + 1) * m
20 | elif ((n // m) % 10) == 1:
21 | ones += (n // m // 10) * m + n % m + 1
22 | m *= 10
23 | return ones
24 |
25 | s = Solution()
26 | print(s.NumberOf1Between1AndN_Solution(526))
27 | print(s.NumberOf1Between1AndN2(526))
--------------------------------------------------------------------------------
/Target Offer/斐波那契数列.py:
--------------------------------------------------------------------------------
1 | '''
2 | 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。
3 | n<=39
4 | '''
5 |
6 | # -*- coding:utf-8 -*-
7 | class Solution:
8 | def Fibonacci(self, n):
9 | tempArray = [0, 1]
10 | if n >= 2:
11 | for i in range(2, n+1):
12 | tempArray[i%2] = tempArray[0] + tempArray[1]
13 | return tempArray[n%2]
14 | # 青蛙跳台阶, 每次可以跳1级或2级
15 | def jumpFloor(self, number):
16 | # write code here
17 | tempArray = [1, 2]
18 | if number >= 3:
19 | for i in range(3, number + 1):
20 | tempArray[(i + 1) % 2] = tempArray[0] + tempArray[1]
21 | return tempArray[(number + 1) % 2]
22 |
23 | def jumpFloorII(self, number):
24 | ans = 1
25 | if number >= 2:
26 | for i in range(number-1):
27 | ans = ans * 2
28 | return ans
29 |
30 | test = Solution()
31 | print(test.Fibonacci(100))
32 | print(test.jumpFloor(3))
33 | print(test.jumpFloorII(2))
--------------------------------------------------------------------------------
/Target Offer/旋转数组的最小数字.py:
--------------------------------------------------------------------------------
1 | '''
2 | 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
3 | 输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。
4 | 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
5 | NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
6 | '''
7 |
8 | # -*- coding:utf-8 -*-
9 | class Solution:
10 | def minNumberInRotateArray(self, rotateArray):
11 | if len(rotateArray) == 0:
12 | return 0
13 | front = 0
14 | rear = len(rotateArray) - 1
15 | minVal = rotateArray[0]
16 | if rotateArray[front] < rotateArray[rear]:
17 | return rotateArray[front]
18 | else:
19 | while (rear - front) > 1:
20 | mid = (rear + front)//2
21 | if rotateArray[mid] > rotateArray[rear]:
22 | front = mid
23 | elif rotateArray[mid] < rotateArray[front]:
24 | rear = mid
25 | elif rotateArray[mid] == rotateArray[front] and rotateArray[front] == rotateArray[rear]:
26 | for i in range(1, len(rotateArray)):
27 | if rotateArray[i] < minVal:
28 | minVal = rotateArray[i]
29 | rear = i
30 | minVal = rotateArray[rear]
31 | return minVal
32 | # 书上方法
33 | def minNumberInRotateArray2(self, rotateArray):
34 | if len(rotateArray) == 0:
35 | return 0
36 | front, rear = 0, len(rotateArray) - 1
37 | midIndex = 0
38 | while rotateArray[front] >= rotateArray[rear]:
39 | if rear - front == 1:
40 | midIndex = rear
41 | break
42 | midIndex = (front + rear) // 2
43 | if rotateArray[front] == rotateArray[rear] and rotateArray[front] == rotateArray[midIndex]:
44 | return self.MinInOrder(rotateArray, front, rear)
45 |
46 | if rotateArray[midIndex] >= rotateArray[front]:
47 | front = midIndex
48 | elif rotateArray[midIndex] <= rotateArray[rear]:
49 | rear = midIndex
50 | return rotateArray[midIndex]
51 | def MinInOrder(self, array, front, end):
52 | result = array[0]
53 | for i in array[front:end+1]:
54 | if i < result:
55 | result = i
56 | return result
57 |
58 | Test = Solution()
59 | print(Test.minNumberInRotateArray([3, 4, 5, 1, 2]))
60 | print(Test.minNumberInRotateArray([1, 2, 3, 4, 5]))
61 | print(Test.minNumberInRotateArray([1, 1, 1, 0, 1]))
62 | print(Test.minNumberInRotateArray([1, 0, 1, 1, 1]))
63 | print(Test.minNumberInRotateArray([]))
64 | print(Test.minNumberInRotateArray([1]))
--------------------------------------------------------------------------------
/Target Offer/替换空格.py:
--------------------------------------------------------------------------------
1 | '''
2 | 请实现一个函数,将一个字符串中的空格替换成“%20”。
3 | 例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
4 | '''
5 |
6 | # -*- coding:utf-8 -*-
7 | class Solution:
8 | # s 源字符串
9 |
10 | # 使用append一次遍历即可替换
11 | # 由于list的append是O(1)的时间复杂度,除了扩容所导致的时间损耗,该算法复杂度为O(n)
12 | def replaceSpaceByAppend(self, s):
13 | string = list(string)
14 | stringReplace = []
15 | for item in string:
16 | if item == ' ':
17 | stringReplace.append('%')
18 | stringReplace.append('2')
19 | stringReplace.append('0')
20 | else:
21 | stringReplace.append(item)
22 | return "".join(stringReplace)
23 |
24 | # 创建新的字符串进行替换
25 | def replaceSpace1(self, s):
26 | tempstr = ''
27 | if type(s) != str:
28 | return
29 | for c in s:
30 | if c == ' ':
31 | tempstr += '%20'
32 | else:
33 | tempstr += c
34 | return tempstr
35 |
36 | # 简单代码替换
37 | # 在Python中str类型是不可变的类型, 使用replace语句会生成一个新的str, 原始的s还是带空格的str变量
38 | def replaceSpace2(self, s):
39 | if type(s) != str:
40 | return
41 | return s.replace(' ', '%20')
42 |
43 | # 书中给的思路
44 | # 判断输入类型的时候,isinstance必须首先判断,因为如果输入为integer的话,没有len,就会直接报错
45 | def replaceSpace3(self, s):
46 | if not isinstance(s,str) or len(s) <= 0 or s == None:
47 | return ""
48 | spaceNum = 0
49 | for i in s:
50 | if i == " ":
51 | spaceNum += 1
52 |
53 | newStrLen = len(s) + spaceNum * 2
54 | newStr = newStrLen * [None]
55 | indexOfOriginal, indexOfNew = len(s) - 1, newStrLen - 1
56 | while indexOfNew >= 0 and indexOfNew >= indexOfOriginal:
57 | if s[indexOfOriginal] == ' ':
58 | newStr[indexOfNew-2:indexOfNew+1] = ['%', '2', '0']
59 | indexOfNew -= 3
60 | indexOfOriginal -= 1
61 | else:
62 | newStr[indexOfNew] = s[indexOfOriginal]
63 | indexOfNew -= 1
64 | indexOfOriginal -= 1
65 | return "".join(newStr)
66 |
67 |
68 | s = 'we are happy'
69 | test = Solution()
70 | print(test.replaceSpace1(s))
71 | print(test.replaceSpace2(s))
72 | print(test.replaceSpace3(s))
73 |
--------------------------------------------------------------------------------
/Target Offer/机器人的运动范围.py:
--------------------------------------------------------------------------------
1 | '''
2 | 地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。
3 | 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。
4 | 但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
5 | '''
6 |
7 | # -*- coding:utf-8 -*-
8 | class Solution:
9 | def movingCount(self, threshold, rows, cols):
10 | visited = [False] * (rows * cols)
11 | count = self.movingCountCore(threshold, rows, cols, 0, 0, visited)
12 | return count
13 |
14 | def movingCountCore(self, threshold, rows, cols, row, col, visited):
15 | count = 0
16 | if self.check(threshold, rows, cols, row, col, visited):
17 | visited[row * cols + col] = True
18 | count = 1 + self.movingCountCore(threshold, rows, cols, row-1, col, visited) + \
19 | self.movingCountCore(threshold, rows, cols, row+1, col, visited) + \
20 | self.movingCountCore(threshold, rows, cols, row, col-1, visited) + \
21 | self.movingCountCore(threshold, rows, cols, row, col+1, visited)
22 | return count
23 |
24 | def check(self, threshold, rows, cols, row, col, visited):
25 | if row >= 0 and row < rows and col >= 0 and col < cols and self.getDigitSum(row) + self.getDigitSum(col) <= threshold and not visited[row * cols + col]:
26 | return True
27 | return False
28 |
29 | def getDigitSum(self, number):
30 | sum = 0
31 | while number > 0:
32 | sum += (number % 10)
33 | number = number // 10
34 | return sum
35 |
36 | s = Solution()
37 | print(s.movingCount(5, 10, 10))
38 |
--------------------------------------------------------------------------------
/Target Offer/构建乘积数组.py:
--------------------------------------------------------------------------------
1 | '''
2 | 给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1]
3 | 其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]。不能使用除法。
4 | '''
5 |
6 | # -*- coding:utf-8 -*-
7 | class Solution:
8 | def multiply(self, A):
9 | if A == None or len(A) <= 0:
10 | return
11 | length = len(A)
12 | aList = [1] * length
13 | for i in range(1, length):
14 | aList[i] = aList[i-1] * A[i-1]
15 | temp = 1
16 | for i in range(length-2, -1, -1):
17 | temp = temp * A[i+1]
18 | aList[i] *= temp
19 | return aList
20 |
21 | test = [1, 2, 3, 4]
22 | s = Solution()
23 | print(s.multiply(test))
--------------------------------------------------------------------------------
/Target Offer/栈的压入弹出序列.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。
3 | 假设压入栈的所有数字均不相等。
4 | 例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,
5 | 但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
6 | '''
7 |
8 | # -*- coding:utf-8 -*-
9 | class Solution:
10 | # 方法1
11 | def IsPopOrder(self, pushV, popV):
12 | if pushV == [] or popV == []:
13 | return False
14 |
15 | stack = []
16 | for i in pushV:
17 | stack.append(i)
18 | if stack[-1] != popV[0]:
19 | continue
20 | else:
21 | stack.pop()
22 | popV.pop(0)
23 | while len(stack) > 0 and stack[-1] == popV[0]:
24 | stack.pop()
25 | popV.pop(0)
26 |
27 | if len(stack) == 0:
28 | return True
29 | else:
30 | return False
31 |
32 | # 方法2, 进行了优化
33 | def IsPopOrder2(self, pushV, popV):
34 | if pushV == [] or popV == []:
35 | return False
36 | stack = []
37 | for i in pushV:
38 | stack.append(i)
39 | while len(stack) and stack[-1] == popV[0]:
40 | stack.pop()
41 | popV.pop(0)
42 | if len(stack):
43 | return False
44 | else:
45 | return True
46 |
47 | pushV = [1, 2, 3, 4, 5]
48 | popV = [4, 5, 3, 2, 1]
49 | popVF = [4, 5, 2, 1, 3]
50 | S = Solution()
51 | print(S.IsPopOrder2(pushV, popVF))
52 |
--------------------------------------------------------------------------------
/Target Offer/树的子结构.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入两棵二叉树A,B,判断B是不是A的子结构
3 | 空树不是任意一个树的子结构
4 | '''
5 |
6 |
7 | class TreeNode:
8 | def __init__(self, x):
9 | self.val = x
10 | self.left = None
11 | self.right = None
12 | class Solution:
13 | def HasSubtree(self, pRoot1, pRoot2):
14 | result = False
15 | if pRoot1 != None and pRoot2 != None:
16 | if pRoot1.val == pRoot2.val:
17 | result = self.DoesTree1haveTree2(pRoot1, pRoot2)
18 | if not result:
19 | result = self.HasSubtree(pRoot1.left, pRoot2)
20 | if not result:
21 | result = self.HasSubtree(pRoot1.right, pRoot2)
22 | return result
23 | # 用于递归判断树的每个节点是否相同
24 | # 需要注意的地方是: 前两个if语句不可以颠倒顺序
25 | # 如果颠倒顺序, 会先判断pRoot1是否为None, 其实这个时候pRoot2的结点已经遍历完成确定相等了, 但是返回了False, 判断错误
26 | def DoesTree1haveTree2(self, pRoot1, pRoot2):
27 | if pRoot2 == None:
28 | return True
29 | if pRoot1 == None:
30 | return False
31 | if pRoot1.val != pRoot2.val:
32 | return False
33 |
34 | return self.DoesTree1haveTree2(pRoot1.left, pRoot2.left) and self.DoesTree1haveTree2(pRoot1.right, pRoot2.right)
35 |
36 | pRoot1 = TreeNode(8)
37 | pRoot2 = TreeNode(8)
38 | pRoot3 = TreeNode(7)
39 | pRoot4 = TreeNode(9)
40 | pRoot5 = TreeNode(2)
41 | pRoot6 = TreeNode(4)
42 | pRoot7 = TreeNode(7)
43 | pRoot1.left = pRoot2
44 | pRoot1.right = pRoot3
45 | pRoot2.left = pRoot4
46 | pRoot2.right = pRoot5
47 | pRoot5.left = pRoot6
48 | pRoot5.right = pRoot7
49 |
50 | pRoot8 = TreeNode(8)
51 | pRoot9 = TreeNode(9)
52 | pRoot10 = TreeNode(2)
53 | pRoot8.left = pRoot9
54 | pRoot8.right = pRoot10
55 |
56 | S = Solution()
57 | print(S.HasSubtree(pRoot1, pRoot8))
--------------------------------------------------------------------------------
/Target Offer/树的宽度.py:
--------------------------------------------------------------------------------
1 | # -*- coding:utf-8 -*-
2 | '''
3 | 求树的宽度
4 | 即树的某层所含结点数目最多, 则打印出该数字
5 | '''
6 |
7 | class TreeNode:
8 | def __init__(self, x):
9 | self.val = x
10 | self.left = None
11 | self.right = None
12 | class Solution:
13 | def widthOfTree(self, pRoot):
14 | if pRoot == None:
15 | return 0
16 | nodeQue = [pRoot]
17 | levelCount, level, maxNum = {0: 1}, 0, 1
18 | while len(nodeQue):
19 | tempQue = nodeQue[:levelCount[level]]
20 | curNodeNum = 0
21 | while len(tempQue) > 0:
22 | tempQue.pop(0)
23 | pNode = nodeQue.pop(0)
24 | if pNode.left:
25 | nodeQue.append(pNode.left)
26 | curNodeNum += 1
27 | if pNode.right:
28 | nodeQue.append(pNode.right)
29 | curNodeNum += 1
30 | level += 1
31 | if level not in levelCount.keys():
32 | levelCount[level] = curNodeNum
33 | if curNodeNum > maxNum:
34 | maxNum = curNodeNum
35 | return maxNum
36 |
37 |
38 | pNode1 = TreeNode(1)
39 | pNode2 = TreeNode(2)
40 | pNode3 = TreeNode(3)
41 | pNode4 = TreeNode(4)
42 | pNode5 = TreeNode(5)
43 | pNode6 = TreeNode(6)
44 | pNode7 = TreeNode(7)
45 |
46 | pNode1.left = pNode2
47 | pNode1.right = pNode3
48 | pNode2.left = pNode4
49 | pNode2.right = pNode5
50 | pNode3.right = pNode6
51 | pNode3.left = pNode7
52 |
53 | S = Solution()
54 | width = S.widthOfTree(pNode1)
55 | print(width)
--------------------------------------------------------------------------------
/Target Offer/格雷码.py:
--------------------------------------------------------------------------------
1 | '''
2 | 在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同, 则称这种编码为格雷码(Gray Code),请编写一个函数,使用递归的方法生成N位的格雷码。
3 | 给定一个整数n,请返回n位的格雷码,顺序为从0开始。
4 | '''
5 |
6 | # -*- coding:utf-8 -*-
7 |
8 | class GrayCode:
9 | def getGray(self, n):
10 | L, L1, L2 = [], [], []
11 | if n == 1:
12 | L = ['0', '1']
13 | else:
14 | L1 = self.getGray(n-1)
15 | L2 = L1[::-1]
16 | num = len(L1)
17 | for i in range(num):
18 | L1[i] = '0' + L1[i]
19 | L2[i] = '1' + L2[i]
20 | L = L1 + L2
21 | return L
22 | s = GrayCode()
23 | print(s.getGray(3))
--------------------------------------------------------------------------------
/Target Offer/正则表达式匹配.py:
--------------------------------------------------------------------------------
1 | '''
2 | 请实现一个函数用来匹配包括'.'和'*'的正则表达式。
3 | 模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。
4 | 在本题中,匹配是指字符串的所有字符匹配整个模式。
5 | 例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配
6 | '''
7 |
8 | # -*- coding:utf-8 -*-
9 | class Solution:
10 | # s, pattern都是字符串
11 | def match(self, s, pattern):
12 | if not s or not pattern:
13 | return False
14 | # 如果s和pattern匹配, 直接True
15 | if s == pattern:
16 | return True
17 | # 如果pattern为'', 因为s和pattern不相等, 直接False
18 | elif pattern == '':
19 | return False
20 | # 当s为'', 如果pattern为'.', 则返回True
21 | # 当s为'', 如果pattern长度为1且不为'.', 或者pattern第二个字符不是*, 则pattern不可能为空, 返回False
22 | # 若pattern长度不为1, 且第二个字符为*, pattern还有空的可能, 从第三个字符开始迭代
23 | elif s == '':
24 | if pattern == ".":
25 | return True
26 | elif len(pattern) == 1 or pattern[1] != '*':
27 | return False
28 | else:
29 | return self.match(s, pattern[2:])
30 | # 如果pattern长度不小于二, 而且pattern的第二个字符不是*的情况下
31 | # 当 pattern[0] 不等于s[0], 且不为 . 的时候, s和pattern必不相等
32 | # 否则, s 和 pattern 都右移一位, 继续比较
33 | if len(pattern) >= 2 and pattern[1] != '*':
34 | if s[0] != pattern[0] and pattern[0] != '.':
35 | return False
36 | else:
37 | return self.match(s[1:], pattern[1:])
38 | # 如果pattern长度不小于2, 且pattern第二个字符为*的情况下
39 | # 如果s[0]不等于pattern[0], 且pattern[0]不为 . , 那么第一位比较不成功, pattern必须后移两位继续比较后面是否能和s第一位匹配
40 | # 如果s[0]等于pattern[0], 或者pattern[0]为 . , 第一位匹配, 那么会有
41 | # 1. aaa 和 a*a 这种情况, 星号代表了多个a, 因此s需要不断右移一位继续比较
42 | # 2. a 和 a*a 中这情况, 这时候星号代表0个a, 因此s不需要右移, pattern需要右移两位
43 | # 3. abc 和 a*bc 这种情况, 星号代表了1个a, s右移一位, pattern右移两位继续比较
44 | elif len(pattern) >= 2 and pattern[1] == '*':
45 | if s[0] != pattern[0] and pattern[0] != '.':
46 | return self.match(s, pattern[2:])
47 | else:
48 | return self.match(s[1:], pattern) or self.match(s, pattern[2:]) or self.match(s[1:], pattern[2:])
49 | # 除去上述pattern不小于2情况, 只剩下pattern等于1的情况, 因此如果pattern为".", 而且s长度为1, 返回True
50 | elif pattern == '.' and len(s) == 1:
51 | return True
52 | return False
53 |
54 |
55 | s = Solution()
56 | print(s.match('aaa', 'a*a'))
--------------------------------------------------------------------------------
/Target Offer/正方体对面和相同.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入一个含有八个数字的数组, 判断有没有可能把这把个数字分别放到正方体的八个顶点上
3 | 使得正方体上三组相对的面上四个顶点的和都相等
4 | '''
5 |
6 | '''
7 | 这个问题其实就是字符串排列的一个衍生问题
8 | 输入一个数组, 生成这八个数字所有可能的排列, 对应到正方体的八个顶点上
9 | 检查是否满足题目要求即可
10 | '''
11 | class Solution:
12 | # 全排列出所有顶点组合
13 | def Permutation(self, pointArr):
14 | if not len(pointArr):
15 | return []
16 | if len(pointArr) == 1:
17 | return pointArr
18 | numList = pointArr
19 | numList.sort()
20 | pStr = []
21 | for i in range(len(numList)):
22 | if i > 0 and numList[i] == numList[i-1]:
23 | continue
24 | temp = self.Permutation(numList[:i] + numList[i+1:])
25 | if type(temp[0]) == int:
26 | for j in temp:
27 | pStr.append([numList[i]] + [j])
28 | else:
29 | for j in temp:
30 | tempArr = [numList[i]] + j
31 | pStr.append(tempArr)
32 | return pStr
33 | def compareSum(self, alist):
34 | allAns = self.Permutation(alist)
35 | for tempList in allAns:
36 | sum1 = tempList[0] + tempList[1] + tempList[2] + tempList[3]
37 | sum2 = tempList[4] + tempList[5] + tempList[6] + tempList[7]
38 | sum3 = tempList[0] + tempList[2] + tempList[4] + tempList[6]
39 | sum4 = tempList[1] + tempList[3] + tempList[5] + tempList[7]
40 | sum5 = tempList[0] + tempList[1] + tempList[4] + tempList[5]
41 | sum6 = tempList[2] + tempList[3] + tempList[6] + tempList[7]
42 | if sum1 == sum2 and sum3 == sum4 and sum5 == sum6:
43 | return True
44 | return False
45 | ss = [2, 3, 9, 7, 0, 11, 2, 6]
46 | ss2 = [1, 1, 1, 1, 1, 1, 1, 1]
47 | s = Solution()
48 | print(s.compareSum(ss2))
--------------------------------------------------------------------------------
/Target Offer/求前n项和.py:
--------------------------------------------------------------------------------
1 | '''
2 | 求1+2+3+...+n,
3 | 要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
4 | '''
5 |
6 |
7 | # -*- coding:utf-8 -*-
8 | class Solution:
9 | def Sum_Solution(self, n):
10 | return self.sumN(n)
11 |
12 | def sum0(self, n):
13 | return 0
14 |
15 | # 利用非0值作两次非运算返回false, 0作两次非运算返回True
16 | def sumN(self, n):
17 | fun = {False: self.sum0, True: self.sumN}
18 | # 此处的fun[not not n] 不能写作func[not not n-1], 否则测试用例为0的话, 就会无限次迭代
19 | return n + fun[not not n](n - 1)
20 |
21 | def Sum_Solution2(self, n):
22 | return n and self.Sum_Solution(n - 1) + n
23 |
24 | s = Solution()
25 | print(s.Sum_Solution(5))
--------------------------------------------------------------------------------
/Target Offer/滑动窗口的最大值.py:
--------------------------------------------------------------------------------
1 | '''
2 | 给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。
3 | 例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,
4 | 他们的最大值分别为{4,4,6,6,6,5};
5 | 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个:
6 | {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
7 | '''
8 |
9 | # -*- coding:utf-8 -*-
10 | class Solution:
11 | def maxInWindows(self, num, size):
12 | if not num or size <= 0:
13 | return []
14 | deque = []
15 | if len(num) >= size:
16 | index = []
17 | for i in range(size):
18 | while len(index) > 0 and num[i] > num[index[-1]]:
19 | index.pop()
20 | index.append(i)
21 |
22 | for i in range(size, len(num)):
23 | deque.append(num[index[0]])
24 | while len(index) > 0 and num[i] >= num[index[-1]]:
25 | index.pop()
26 | if len(index) > 0 and index[0] <= i - size:
27 | index.pop(0)
28 | index.append(i)
29 |
30 | deque.append(num[index[0]])
31 | return deque
32 |
33 | test = [2, 3, 4, 2, 6, 2, 5, 1]
34 | s = Solution()
35 | print(s.maxInWindows(test, 3))
36 |
37 |
--------------------------------------------------------------------------------
/Target Offer/用两个栈实现队列.py:
--------------------------------------------------------------------------------
1 | '''
2 | 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
3 | '''
4 |
5 | # -*- coding:utf-8 -*-
6 | class Solution:
7 | def __init__(self):
8 | self.stack1 = []
9 | self.stack2 = []
10 | def push(self, node):
11 | self.stack1.append(node)
12 | def pop(self):
13 | if len(self.stack2) == 0 and len(self.stack1) == 0:
14 | return
15 | elif len(self.stack2) == 0:
16 | while len(self.stack1) > 0:
17 | self.stack2.append(self.stack1.pop())
18 | return self.stack2.pop()
19 |
20 | P = Solution()
21 | P.push(10)
22 | P.push(11)
23 | P.push(12)
24 | print(P.pop())
25 | P.push(13)
26 | print(P.pop())
27 | print(P.pop())
28 | print(P.pop())
29 | print(P.pop())
30 |
--------------------------------------------------------------------------------
/Target Offer/用两个队列实现栈.py:
--------------------------------------------------------------------------------
1 | # -*- coding:UTF-8 -*-
2 | '''
3 | 两个队列实现栈
4 | '''
5 | class Solution:
6 | def __init__(self):
7 | self.queue1 = []
8 | self.queue2 = []
9 | def push(self, x):
10 | if self.queue2 == []:
11 | self.queue1.append(x)
12 | else:
13 | self.queue2.append(x)
14 | def pop(self):
15 | if not self.queue1 and not self.queue2:
16 | return
17 | if self.queue1 != []:
18 | length = len(self.queue1)
19 | for i in range(length-1):
20 | self.queue2.append(self.queue1.pop(0))
21 | return self.queue1.pop()
22 | else:
23 | length = len(self.queue2)
24 | for i in range(length-1):
25 | self.queue1.append(self.queue2.pop(0))
26 | return self.queue2.pop()
27 |
28 | P = Solution()
29 | P.push(10)
30 | P.push(11)
31 | P.push(12)
32 | print(P.pop())
33 | P.push(13)
34 | print(P.pop())
35 | print(P.pop())
36 | print(P.pop())
37 | print(P.pop())
38 |
--------------------------------------------------------------------------------
/Target Offer/矩阵中的路径.py:
--------------------------------------------------------------------------------
1 | '''
2 | 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。
3 | 路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。
4 | 如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。
5 | 例如 [[a b c e], [s f c s], [a d e e]] 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,
6 | 因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
7 | '''
8 |
9 | # -*- coding:utf-8 -*-
10 | class Solution:
11 | def hasPath(self, matrix, rows, cols, path):
12 | if matrix == None or rows < 1 or cols < 1 or path == None:
13 | return False
14 | visited = [0] * (rows * cols)
15 |
16 | pathLength = 0
17 | for row in range(rows):
18 | for col in range(cols):
19 | if self.hasPathCore(matrix, rows, cols, row, col, path, pathLength, visited):
20 | return True
21 | return False
22 |
23 | def hasPathCore(self, matrix, rows, cols, row, col, path, pathLength, visited):
24 | if len(path) == pathLength:
25 | return True
26 |
27 | hasPath = False
28 | if row >= 0 and row < rows and col >= 0 and col < cols and matrix[row * cols + col] == path[pathLength] and not \
29 | visited[row * cols + col]:
30 |
31 | pathLength += 1
32 | visited[row * cols + col] = True
33 |
34 | hasPath = self.hasPathCore(matrix, rows, cols, row, col - 1, path, pathLength, visited) or \
35 | self.hasPathCore(matrix, rows, cols, row - 1, col, path, pathLength, visited) or \
36 | self.hasPathCore(matrix, rows, cols, row, col + 1, path, pathLength, visited) or \
37 | self.hasPathCore(matrix, rows, cols, row + 1, col, path, pathLength, visited)
38 |
39 | if not hasPath:
40 | pathLength -= 1
41 | visited[row * cols + col] = False
42 |
43 | return hasPath
44 |
45 | s = Solution()
46 | ifTrue = s.hasPath("ABCESFCSADEE", 3, 4, "ABCCED")
47 | ifTrue2 = s.hasPath("ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS", 5, 8, "SGGFIECVAASABCEHJIGQEM")
48 | print(ifTrue2)
--------------------------------------------------------------------------------
/Target Offer/第一个只出现一次的字符.py:
--------------------------------------------------------------------------------
1 | '''
2 | 在一个字符串(1<=字符串长度<=10000,全部由大写字母组成)中找到第一个只出现一次的字符。
3 | '''
4 |
5 | # -*- coding:utf-8 -*-
6 | class Solution:
7 | def FirstNotRepeatingChar(self, s):
8 | if s == None or len(s) <= 0:
9 | return -1
10 | alphabet = {}
11 | alist = list(s)
12 | for i in alist:
13 | if i not in alphabet.keys():
14 | alphabet[i] = 0
15 | alphabet[i] += 1
16 | for i in alist:
17 | if alphabet[i] == 1:
18 | return i
19 | return -1
20 |
21 | s = Solution()
22 | print(s.FirstNotRepeatingChar('abaccdeff'))
--------------------------------------------------------------------------------
/Target Offer/约瑟夫环.py:
--------------------------------------------------------------------------------
1 | '''
2 | 0, 1, 2, n-1这n个数字排成一个圆环, 从数字0开始每次从这个圆圈里删除第m个数字
3 | 求这个圆圈中最后剩下的一个数字
4 | '''
5 |
6 | # -*- coding:utf-8 -*-
7 | class Solution:
8 | def LastRemaining_Solution(self, n, m):
9 | if n < 1 or m < 1:
10 | return -1
11 | remainIndex = 0
12 | for i in range(1, n+1):
13 | remainIndex = (remainIndex + m) % i
14 | return remainIndex
--------------------------------------------------------------------------------
/Target Offer/翻转单词顺序.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入一个英文句子, 翻转句子中单词的顺序,但单词内字符的顺序不变
3 | 为简单起见, 标点符号和普通字母一样处理
4 | '''
5 |
6 | # -*- coding:utf-8 -*-
7 | class Solution:
8 | # 按照书上的方法进行编写
9 | # 因为Python的字符串结束没有结束符, 所以需要判断最后的pEnd是否已经指到最后一个字符
10 | # 如果已经指到最后一个字符, 则直接在复制之后跳出循环
11 | # 测试用例'I am a student.'和' '和''
12 | def ReverseSentence(self, s):
13 | if s == None or len(s) <= 0:
14 | return ''
15 | strList = list(s)
16 | strList = self.Reverse(strList)
17 | pBegin = 0
18 | pEnd = 0
19 | resultStr = ''
20 | listTemp = []
21 |
22 | while pEnd < len(s):
23 | # 如果字符串长度为1, 直接跳出循环
24 | # 如果pEnd指针指到最后一个字符, 跳出循环
25 | if pEnd == len(s)-1:
26 | listTemp.append(self.Reverse(strList[pBegin:]))
27 | break
28 | # 这个判断语句位置需要靠前, 用来鉴定字符串开头是否是空格的情况
29 | if strList[pBegin] == ' ':
30 | pBegin += 1
31 | pEnd += 1
32 | listTemp.append(' ')
33 | elif strList[pEnd] == ' ':
34 | listTemp.append(self.Reverse(strList[pBegin:pEnd]))
35 | pBegin = pEnd
36 | else:
37 | pEnd += 1
38 | # print(listTemp)
39 | for i in listTemp:
40 | resultStr += ''.join(i)
41 | return resultStr
42 | # 翻转字符list
43 | def Reverse(self, alist):
44 | if alist == None or len(alist) <= 0:
45 | return ''
46 | startIndex = 0
47 | endIndex = len(alist) - 1
48 | while startIndex < endIndex:
49 | alist[startIndex], alist[endIndex] = alist[endIndex], alist[startIndex]
50 | startIndex += 1
51 | endIndex -= 1
52 | return alist
53 |
54 | # 直接利用Python的语句进行字符串的翻转
55 | def ReverseSentence2(self, s):
56 | l = s.split(' ')
57 | return ' '.join(l[::-1])
58 |
59 |
60 | str = 'I am a student.'
61 | s = Solution()
62 | print(s.ReverseSentence2(str))
--------------------------------------------------------------------------------
/Target Offer/表示数值的字符串.py:
--------------------------------------------------------------------------------
1 | '''
2 | 请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。
3 | 例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。
4 | 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。
5 | '''
6 |
7 | # -*- coding:utf-8 -*-
8 | class Solution:
9 | # s字符串
10 | def isNumeric(self, s):
11 | if s == None or len(s) <= 0:
12 | return False
13 | aList = [w.lower() for w in s]
14 | if 'e' in aList:
15 | indexE = aList.index('e')
16 | front = aList[:indexE]
17 | behind = aList[indexE+1:]
18 | if '.' in behind or len(behind) == 0:
19 | return False
20 | isFront = self.scanDigit(front)
21 | isBehind = self.scanDigit(behind)
22 | return isBehind and isFront
23 | else:
24 | isNum = self.scanDigit(aList)
25 | return isNum
26 |
27 | def scanDigit(self, alist):
28 | dotNum = 0
29 | allowVal = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '-', '.', 'e']
30 | for i in range(len(alist)):
31 | if alist[i] not in allowVal:
32 | return False
33 | if alist[i] == '.':
34 | dotNum += 1
35 | if alist[i] in '+-' and i != 0:
36 | return False
37 | if dotNum > 1:
38 | return False
39 | return True
40 |
41 | # Python trick
42 | def isNumeric2(self, s):
43 | try:
44 | float(s)
45 | if s[0:2] != '-+' and s[0:2] != '+-':
46 | return True
47 | else:
48 | return False
49 | except:
50 | return False
51 |
52 | s = Solution()
53 | print(s.isNumeric2('12a5'))
--------------------------------------------------------------------------------
/Target Offer/调整数组顺序使奇数位于偶数前面.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分
3 | 所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
4 | '''
5 |
6 |
7 | class Solution:
8 | # 一个类似于快排的方法, 只是简单的满足了奇数在前,偶数在后, 奇数的顺序发生了改变
9 | def reOrderArray(self, array):
10 | if len(array) < 1:
11 | return
12 | elif len(array) == 1:
13 | return array
14 |
15 | front = 0
16 | rear = len(array)-1
17 | while front <= rear:
18 | while array[front] & 0x1 == 1:
19 | front += 1
20 | while array[rear] & 0x1 == 0:
21 | rear -= 1
22 | array[front], array[rear] = array[rear], array[front]
23 | array[front], array[rear] = array[rear], array[front]
24 | return array
25 | # 直接利用Python的trick, 写一个简单的排列数组, 顺序不变
26 | def reOrderArray2(self, array):
27 | left = [x for x in array if x & 1]
28 | right = [x for x in array if not x & 1]
29 | return left + right
30 |
31 | def reOrderArray3(self, array):
32 | if len(array) < 1:
33 | return []
34 | if len(array) == 1:
35 | return array
36 | arrayOdd = []
37 | arrayEven = []
38 | for num in array:
39 | if num & 0x1:
40 | arrayOdd.append(num)
41 | else:
42 | arrayEven.append(num)
43 | return arrayOdd+arrayEven
44 |
45 | # 可扩展性的解法
46 | # 注意在一个函数的输入中, 输入另一个函数的写法func = self.fucName, funcName不需要加括号
47 | def Reorder(self, pData, length, func):
48 | if length == 0:
49 | return
50 |
51 | pBegin = 0
52 | pEnd = length - 1
53 |
54 | while pBegin < pEnd:
55 | while pBegin < pEnd and not func(pData[pBegin]):
56 | pBegin += 1
57 | while pBegin < pEnd and func(pData[pEnd]):
58 | pEnd -= 1
59 |
60 | if pBegin < pEnd:
61 | pData[pBegin], pData[pEnd] = pData[pEnd], pData[pBegin]
62 | return pData
63 |
64 | def isEven(self, n):
65 | return not n & 0x1
66 |
67 | def isNegtive(self, n):
68 | return n >= 0
69 |
70 | def ReorderOddEven(self, pData):
71 | length = len(pData)
72 | return self.Reorder(pData, length, func=self.isNegtive)
73 |
74 |
75 | S = Solution()
76 | # print(S.reOrderArray3([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]))
77 | # print(S.ReorderOddEven([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]))
78 | print(S.ReorderOddEven([-1, 2, -3, 4, -5, -6, 7, 8, 9, 10, -10]))
--------------------------------------------------------------------------------
/Target Offer/转换字符串格式.py:
--------------------------------------------------------------------------------
1 | '''
2 | 转换字符串格式为原来字符串里的字符+该字符连续出现的个数
3 | 例如1233422222, 转化为1121324125
4 | '''
5 |
6 | def convertString(string):
7 | if string == None or len(string) <= 0:
8 | return
9 | outputStr = ""
10 | length = len(string)
11 | index = 0
12 | while index < length:
13 | count = 0
14 | while index+count < length and string[index] == string[index+count]:
15 | count += 1
16 | outputStr += string[index] + str(count)
17 | index += count
18 | return outputStr
19 |
20 | # 可以用来判断字符串标识的函数, 比如Mississippi转化为"i4m1p2s4"
21 | # 这里讲次数出现1次的省去, Mississippi转化为"mi4s4p2"
22 | def convertString2(string):
23 | if string == None or len(string) <= 0:
24 | return
25 | string.lower()
26 | outputStr = ""
27 | dictSet = {}
28 | for i in string:
29 | if i not in dictSet.keys():
30 | dictSet[i] = 0
31 | dictSet[i] += 1
32 | for i in string:
33 | if i in outputStr: continue
34 | outputStr += (i + str(dictSet[i])) if dictSet[i] != 1 else i
35 | return outputStr
36 |
37 | print(convertString("1233422222"))
38 | print(convertString("a"))
39 | print(convertString2("mississippi"))
40 |
--------------------------------------------------------------------------------
/Target Offer/输出连续质数序列.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入一个整数, 输出不大于这个整数的所有连续的质数序列
3 | 认为1不是质数
4 | '''
5 |
6 | def Sieve(n):
7 | if n == None or n <= 1:
8 | return
9 | temp = [0]*(n+1)
10 | for p in range(2, len(temp)):
11 | temp[p] = p
12 | for p in range(2, int(n**0.5)+1):
13 | if temp[p] != 0:
14 | j = p * p
15 | while j <= n:
16 | temp[j] = 0
17 | j += p
18 | output = []
19 | for i in temp:
20 | if i != 0:
21 | output.append(i)
22 | return output
23 |
24 | print(Sieve(29))
--------------------------------------------------------------------------------
/Target Offer/连续子数组的最大和.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入一个整型数组,数组里有整数也有负数。
3 | 数组中一二或连续的多个整数组成一个子数组。求所有子数组的和的最大值。
4 | 要求时间复杂度为O(n)
5 | '''
6 |
7 | # -*- coding:utf-8 -*-
8 | class Solution:
9 | def FindGreatestSumOfSubArray(self, array):
10 | if array == None or len(array) <= 0:
11 | return 0
12 |
13 | nCurSum = 0
14 | nGreatestSum = array[0]
15 | for i in range(len(array)):
16 | if nCurSum <= 0:
17 | nCurSum = array[i]
18 | else:
19 | nCurSum += array[i]
20 |
21 | if nCurSum > nGreatestSum:
22 | nGreatestSum = nCurSum
23 |
24 | return nGreatestSum
25 | # 动态规划解决问题
26 | def FindGreatestSumOfSubArray2(self, array):
27 | if array == None or len(array) <= 0:
28 | return 0
29 | aList = [0]*len(array)
30 | for i in range(len(array)):
31 | if i == 0 or aList[i-1] <= 0:
32 | aList[i] = array[i]
33 | else:
34 | aList[i] = aList[i-1] + array[i]
35 | return max(aList)
36 |
37 |
38 |
39 | alist = [1, -2, 3, 10, -4, 7, 2, -5]
40 | s = Solution()
41 | print(s.FindGreatestSumOfSubArray2(alist))
--------------------------------------------------------------------------------
/Target Offer/重建二叉树.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。
3 | 假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
4 | 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
5 | '''
6 |
7 | # -*- coding:utf-8 -*-
8 | class TreeNode:
9 | def __init__(self, x):
10 | self.val = x
11 | self.left = None
12 | self.right = None
13 | class Solution:
14 | # 返回构造的TreeNode根节点
15 | def reConstructBinaryTree(self, pre, tin):
16 | # write code here
17 | if not pre and not tin:
18 | return None
19 | root = TreeNode(pre[0])
20 | if set(pre) != set(tin):
21 | return None
22 | i = tin.index(pre[0])
23 | root.left = self.reConstructBinaryTree(pre[1:i+1], tin[:i])
24 | root.right = self.reConstructBinaryTree(pre[i+1:], tin[i+1:])
25 | return root
26 |
27 | pre = [1, 2, 3, 5, 6, 4]
28 | tin = [5, 3, 6, 2, 4, 1]
29 | test = Solution()
30 | newTree = test.reConstructBinaryTree(pre, tin)
31 | # 按层序遍历输出树中某一层的值
32 | def PrintNodeAtLevel(treeNode, level):
33 | if not treeNode or level < 0:
34 | return 0
35 | if level == 0:
36 | print(treeNode.val)
37 | return 1
38 | PrintNodeAtLevel(treeNode.left, level-1)
39 | PrintNodeAtLevel(treeNode.right, level-1)
40 |
41 | # 已知树的深度按层遍历输出树的值
42 | def PrintNodeByLevel(treeNode, depth):
43 | for level in range(depth):
44 | PrintNodeAtLevel(treeNode, level)
45 |
46 | # # 不知道树的深度直接按层遍历输出树的值
47 | ####有bug, 待修复
48 | # def PrintNodeByLevel2(treeNode):
49 | # level = 0
50 | # while 1:
51 | # if not PrintNodeAtLevel(treeNode, level):
52 | # break
53 | # level = level + 1
54 |
55 |
56 | PrintNodeByLevel(newTree, 5)
57 | # PrintNodeByLevel2(newTree)
58 |
--------------------------------------------------------------------------------
/Target Offer/链表中倒数第k个结点.py:
--------------------------------------------------------------------------------
1 | '''
2 | 输入一个链表,输出该链表中倒数第k个结点。
3 | '''
4 |
5 | '''
6 | 这道题的思路很好
7 | 如果在只希望一次遍历的情况下, 寻找倒数第k个结点, 可以设置两个指针
8 | 第一个指针先往前走k-1步, 然后从第k步开始第二个指针指向头结点
9 | 然后两个指针一起遍历
10 | 当地一个指针指向尾节点的时候, 第二个指针正好指向倒数第k个结点
11 | 推广: 寻找中间节点, 两个指针一起, 第一个指针每次走两步, 第二个指针每次走一步, 快指针指到尾部, 慢指针正好指到中间
12 | '''
13 |
14 | # -*- coding:utf-8 -*-
15 | class ListNode:
16 | def __init__(self, x):
17 | self.val = x
18 | self.next = None
19 |
20 | class Solution:
21 | def FindKthToTail(self, head, k):
22 | if head == None or k <= 0:
23 | return None
24 |
25 | pAHead = head
26 | pBehind = None
27 |
28 | for i in range(k-1):
29 | if pAHead.next != None:
30 | pAHead = pAHead.next
31 | else:
32 | return None
33 | pBehind = head
34 | while pAHead.next != None:
35 | pAHead = pAHead.next
36 | pBehind = pBehind.next
37 | return pBehind
38 |
39 | node1 = ListNode(10)
40 | node2 = ListNode(11)
41 | node3 = ListNode(13)
42 | node1.next = node2
43 | node2.next = node3
44 |
45 | S = Solution()
46 | print(S.FindKthToTail(node1, 1).val)
--------------------------------------------------------------------------------
/Target Offer/链表中环的入口结点.py:
--------------------------------------------------------------------------------
1 | '''
2 | 一个链表中包含环,请找出该链表的环的入口结点。
3 | '''
4 |
5 | # -*- coding:utf-8 -*-
6 | class ListNode:
7 | def __init__(self, x):
8 | self.val = x
9 | self.next = None
10 | class Solution:
11 | def MeetingNode(self, pHead):
12 | if pHead == None:
13 | return None
14 |
15 | pSlow = pHead.next
16 | if pSlow == None:
17 | return None
18 | pFast = pSlow.next
19 | while pFast:
20 | if pSlow == pFast:
21 | return pSlow
22 | pSlow = pSlow.next
23 | pFast = pFast.next
24 | if pFast:
25 | pFast = pFast.next
26 |
27 | def EntryNodeOfLoop(self, pHead):
28 | meetingNode = self.MeetingNode(pHead)
29 | if not meetingNode:
30 | return None
31 |
32 | NodeLoop = 1
33 | flagNode = meetingNode
34 | while flagNode.next != meetingNode:
35 | NodeLoop += 1
36 | flagNode = flagNode.next
37 |
38 | pFast = pHead
39 | for i in range(NodeLoop):
40 | pFast = pFast.next
41 | pSlow = pHead
42 | while pFast != pSlow:
43 | pFast = pFast.next
44 | pSlow = pSlow.next
45 | return pFast
46 |
47 | node1 = ListNode(1)
48 | node2 = ListNode(2)
49 | node3 = ListNode(3)
50 | node4 = ListNode(4)
51 | node5 = ListNode(5)
52 | node6 = ListNode(6)
53 |
54 | node1.next = node2
55 | node2.next = node3
56 | node3.next = node4
57 | node4.next = node5
58 | node5.next = node6
59 | node6.next = node3
60 |
61 | s = Solution()
62 | print(s.EntryNodeOfLoop(node1).val)
--------------------------------------------------------------------------------
/Target Offer/零钱找零以及进阶:
--------------------------------------------------------------------------------
1 | '''
2 | 零钱找零问题,使用动态规划
3 | '''
4 | def ChangeMaking(coinVal, change):
5 | alist = [0]*(change+1)
6 | for i in range(1, change+1):
7 | temp = change; j = 0
8 | while j <= len(coinVal)-1 and i >= coinVal[j]:
9 | temp = min(alist[i-coinVal[j]], temp)
10 | j += 1
11 | alist[i] = temp + 1
12 | return alist.pop()
13 |
14 | print(ChangeMaking([1, 5, 10, 25], 63))
15 |
16 | '''
17 | 零钱找零问题的进阶
18 | 美团笔试题
19 | 给你六中零钱1,5,10,20,50,100的纸币,给定一个金额,写出所有可能的找零的个数
20 | 输入2,输出1;输入5,输出2
21 | 也是使用动态规划
22 | '''
23 | import sys
24 | try:
25 | while True:
26 | line = sys.stdin.readline().strip()
27 | if line == '':
28 | break
29 | target = int(line)
30 | coinVal = [1, 5, 10, 20, 50, 100]
31 | alist = [0]*(target+1)
32 | alist[0] = 1
33 | for i in range(6):
34 | j = coinVal[i]
35 | while j <= target:
36 | alist[j] = alist[j] + alist[j-coinVal[i]]
37 | j += 1
38 | print(alist[-1])
39 | except:
40 | pass
41 |
--------------------------------------------------------------------------------
/__pycache__/BinaryTree.cpython-34.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jack-Lee-Hiter/AlgorithmsByPython/78d7ac4d93db9da40601a5567350bfb3e97e7d46/__pycache__/BinaryTree.cpython-34.pyc
--------------------------------------------------------------------------------
/__pycache__/Stack.cpython-34.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jack-Lee-Hiter/AlgorithmsByPython/78d7ac4d93db9da40601a5567350bfb3e97e7d46/__pycache__/Stack.cpython-34.pyc
--------------------------------------------------------------------------------
/__pycache__/mysingleton.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jack-Lee-Hiter/AlgorithmsByPython/78d7ac4d93db9da40601a5567350bfb3e97e7d46/__pycache__/mysingleton.cpython-35.pyc
--------------------------------------------------------------------------------
/divideAndConquer.py:
--------------------------------------------------------------------------------
1 | '''
2 | 分治算法一般都伴随着递归算法
3 | '''
4 | # 分治算法实现查找数组中的最大元素的位置
5 | def maxIndex(alist, start, end):
6 | if start > end or len(alist) == 0:
7 | return
8 | pivot = (start+end) >> 1
9 | if end - start == 1:
10 | return start
11 | else:
12 | temp1 = maxIndex(alist, start, pivot)
13 | temp2 = maxIndex(alist, pivot, end)
14 | if alist[temp1] < alist[temp2]:
15 | return temp2
16 | else:
17 | return temp1
18 | print(maxIndex([5,7,9,3,4,8,6,2,0,1], 0, 9))
19 |
20 | # 分治法计算正整数幂
21 | def power(base, x):
22 | if x == 1:
23 | return base
24 | else:
25 | if x & 1 == 1:
26 | return power(base, x>>1)*power(base, x>>1)*base
27 | else:
28 | return power(base, x>>1)*power(base, x>>1)
29 |
30 | print(power(2, 6))
--------------------------------------------------------------------------------
/heapSort.py:
--------------------------------------------------------------------------------
1 | def heapSort(alist):
2 | if alist == None or len(alist) == 0:
3 | return
4 | length = len(alist)
5 | output = []
6 | for i in range(length):
7 | tempLen = len(alist)
8 | for j in range(tempLen//2-1, -1, -1):
9 | preIndex = j
10 | preVal, heap = alist[preIndex], False
11 | while 2 * preIndex < tempLen - 1 and not heap:
12 | curIndex = 2 * preIndex + 1
13 | if curIndex < tempLen - 1:
14 | if alist[curIndex] < alist[curIndex+1]:
15 | curIndex += 1
16 | if preVal >= alist[curIndex]:
17 | heap = True
18 | else:
19 | alist[preIndex] = alist[curIndex]
20 | preIndex = curIndex
21 | alist[preIndex] = preVal
22 | output.insert(0, alist.pop(0))
23 | return output
24 |
25 | test = [2, 6, 5, 9, 10, 3, 7]
26 | print(heapSort(test))
27 |
--------------------------------------------------------------------------------
/leetcode/1. Two Sum.py:
--------------------------------------------------------------------------------
1 | '''
2 | Given an array of integers, return indices of the two numbers such that they add up to a specific target.
3 | You may assume that each input would have exactly one solution.
4 | Given nums = [2, 7, 11, 15], target = 9,
5 | Because nums[0] + nums[1] = 2 + 7 = 9,
6 | return [0, 1].
7 | '''
8 |
9 | class Solution():
10 | def twoSum(self, nums, target):
11 | hashdict = {}
12 | for i, item in enumerate(nums):
13 | if (target - item) in hashdict:
14 | return (hashdict[target - item], i)
15 | hashdict[item] = i
16 | return (-1, -1)
17 | s = Solution()
18 | print(s.twoSum([2, 7, 11, 15], 9))
--------------------------------------------------------------------------------
/leetcode/101. Symmetric Tree.py:
--------------------------------------------------------------------------------
1 | '''
2 | Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).
3 |
4 | For example, this binary tree [1,2,2,3,4,4,3] is symmetric:
5 |
6 | 1
7 | / \
8 | 2 2
9 | / \ / \
10 | 3 4 4 3
11 | But the following [1,2,2,null,3,null,3] is not:
12 | 1
13 | / \
14 | 2 2
15 | \ \
16 | 3 3
17 | '''
18 |
19 | class TreeNode(object):
20 | def __init__(self, x):
21 | self.val = x
22 | self.left = None
23 | self.right = None
24 |
25 | class Solution(object):
26 | # recursive
27 | def isSymmetric(self, root):
28 | return self._Symmetrical(root, root)
29 | def _Symmetrical(self, pRoot1, pRoot2):
30 | if pRoot1 and pRoot2:
31 | return pRoot1.val == pRoot2.val and self._Symmetrical(pRoot1.left, pRoot2.right) and self._Symmetrical(
32 | pRoot1.right, pRoot2.left)
33 | else:
34 | return pRoot1 == pRoot2
35 |
36 | #iterative(BFS)
37 | def isSymmetric2(self, root):
38 | if root:
39 | now = [root]
40 | while now:
41 | vals = [i.val if i else None for i in now]
42 | if list(reversed(vals)) != vals:
43 | return False
44 | else:
45 | now = [j for i in now if i for j in (i.left, i.right)]
46 | return True
47 | # modify iterative(BFS)
48 | def isSymmetric_2(self, root):
49 | if root:
50 | nodeStack = [root]
51 | while nodeStack:
52 | vals = [node.val if node else None for node in nodeStack]
53 | if list(reversed(vals)) != vals:
54 | return False
55 | else:
56 | preStack = [node for node in nodeStack if node]
57 | nodeStack = []
58 | for preNode in preStack:
59 | nodeStack.append(preNode.left)
60 | nodeStack.append(preNode.right)
61 | return True
62 |
63 | # iterative(DFS)
64 | def isSymmetric3(self, root):
65 | if root:
66 | stack = [(root.left, root.right)]
67 | while len(stack) > 0:
68 | p, q = stack.pop()
69 | if p and q and p.val == q.val:
70 | stack.append((p.left, q.right))
71 | stack.append((p.right, q.left))
72 | elif p != q:
73 | return False
74 | return True
75 |
76 |
--------------------------------------------------------------------------------
/leetcode/102. Binary Tree Level Order Traversal.py:
--------------------------------------------------------------------------------
1 | '''
2 | Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level).
3 |
4 | For example:
5 | Given binary tree [3,9,20,null,null,15,7],
6 | 3
7 | / \
8 | 9 20
9 | / \
10 | 15 7
11 | return its level order traversal as:
12 | [
13 | [3],
14 | [9,20],
15 | [15,7]
16 | ]
17 | '''
18 | # Definition for a binary tree node.
19 | class TreeNode(object):
20 | def __init__(self, x):
21 | self.val = x
22 | self.left = None
23 | self.right = None
24 |
25 | class Solution(object):
26 | def levelOrder(self, root):
27 | if not root:
28 | return []
29 | res, level = [], [root]
30 | while level:
31 | res.append([node.val for node in level])
32 | temp = []
33 | for node in level:
34 | temp.extend([node.left, node.right])
35 | level = [node for node in temp if node]
36 | return res
--------------------------------------------------------------------------------
/leetcode/103. Binary Tree Zigzag Level Order Traversal.py:
--------------------------------------------------------------------------------
1 | '''
2 | Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between).
3 |
4 | For example:
5 | Given binary tree [3,9,20,null,null,15,7],
6 | 3
7 | / \
8 | 9 20
9 | / \
10 | 15 7
11 | return its zigzag level order traversal as:
12 | [
13 | [3],
14 | [20,9],
15 | [15,7]
16 | ]
17 | '''
18 | # Definition for a binary tree node.
19 | class TreeNode:
20 | def __init__(self, x):
21 | self.val = x
22 | self.left = None
23 | self.right = None
24 |
25 | class Solution:
26 | def zigzagLevelOrder(self, root):
27 | if not root:
28 | return []
29 | levels, result, leftToRight = [root], [], True
30 | while levels:
31 | curValues, nextLevel = [], []
32 | for node in levels:
33 | curValues.append(node.val)
34 | if node.left:
35 | nextLevel.append(node.left)
36 | if node.right:
37 | nextLevel.append(node.right)
38 | if not leftToRight:
39 | curValues.reverse()
40 | if curValues:
41 | result.append(curValues)
42 | levels = nextLevel
43 | leftToRight = not leftToRight
44 | return result
45 |
46 |
47 | pNode1 = TreeNode(8)
48 | pNode2 = TreeNode(6)
49 | pNode3 = TreeNode(10)
50 | pNode4 = TreeNode(5)
51 | pNode5 = TreeNode(7)
52 | pNode6 = TreeNode(9)
53 | pNode7 = TreeNode(11)
54 |
55 | pNode1.left = pNode2
56 | pNode1.right = pNode3
57 | pNode2.left = pNode4
58 | pNode2.right = pNode5
59 | pNode3.left = pNode6
60 | pNode3.right = pNode7
61 |
62 | S = Solution()
63 | aList = S.zigzagLevelOrder(pNode1)
64 | print(aList)
--------------------------------------------------------------------------------
/leetcode/105. Construct Binary Tree from Preorder and Inorder Traversal.py:
--------------------------------------------------------------------------------
1 | '''
2 | Given preorder and inorder traversal of a tree, construct the binary tree.
3 | '''
4 | class TreeNode(object):
5 | def __init__(self, x):
6 | self.val = x
7 | self.left = None
8 | self.right = None
9 |
10 | class Solution(object):
11 | # recursion
12 | def buildTree(self, preorder, inorder):
13 | if not preorder or not inorder:
14 | return
15 | root = TreeNode(preorder[0])
16 | ind = inorder.index(preorder.pop(0))
17 | root.left = self.buildTree(preorder, inorder[0:ind])
18 | root.right = self.buildTree(preorder, inorder[ind + 1:])
19 | return root
20 | # method2, faster!!
21 | def buildTree2(self, preorder, inorder):
22 | self.Ind = 0
23 | ind = {val: ind for ind, val in enumerate(inorder)}
24 | head = self.build(0, len(preorder) - 1, preorder, inorder, ind)
25 | return head
26 |
27 | def build(self, start, end, preorder, inorder, ind):
28 | if start <= end:
29 | mid = ind[preorder[self.Ind]]
30 | self.Ind += 1
31 | root = TreeNode(inorder[mid])
32 | root.left = self.build(start, mid - 1, preorder, inorder, ind)
33 | root.right = self.build(mid + 1, end, preorder, inorder, ind)
34 | return root
35 | # Interative
36 | def buildTreeInter(self, preorder, inorder):
37 | if len(preorder) == 0:
38 | return None
39 |
40 | head = TreeNode(preorder[0])
41 | stack = [head]
42 | preInd, inInd = 1, 0
43 |
44 | while preInd < len(preorder):
45 | temp = None
46 | node = TreeNode(preorder[preInd])
47 | while stack and stack[-1].val == inorder[inInd]:
48 | temp = stack.pop()
49 | inInd += 1
50 | if temp:
51 | temp.right = node
52 | else:
53 | stack[-1].left = node
54 | stack.append(node)
55 | preInd += 1
56 |
57 | return head
--------------------------------------------------------------------------------
/leetcode/106. Construct Binary Tree from Inorder and Postorder Traversal.py:
--------------------------------------------------------------------------------
1 | '''
2 | Given inorder and postorder traversal of a tree, construct the binary tree.
3 | '''
4 |
5 | # Definition for a binary tree node.
6 | class TreeNode(object):
7 | def __init__(self, x):
8 | self.val = x
9 | self.left = None
10 | self.right = None
11 |
12 | class Solution(object):
13 | def buildTree(self, inorder, postorder):
14 | if not inorder or not postorder:
15 | return None
16 |
17 | root = TreeNode(postorder.pop())
18 | ind = inorder.index(root.val)
19 |
20 | root.right = self.buildTree(inorder[ind + 1:], postorder)
21 | root.left = self.buildTree(inorder[:ind], postorder)
22 | return root
23 |
24 | # method2, faster!!
25 | def buildTree2(self, inorder, postorder):
26 | self.postInd = len(postorder) - 1
27 | ind = {val: ind for ind, val in enumerate(inorder)}
28 | head = self.build(0, len(postorder) - 1, inorder, postorder, ind)
29 | return head
30 |
31 | def build(self, start, end, inorder, postorder, ind):
32 | if start <= end:
33 | mid = ind[postorder[self.postInd]]
34 | self.postInd -= 1
35 | root = TreeNode(inorder[mid])
36 | root.right = self.build(mid + 1, end, inorder, postorder, ind)
37 | root.left = self.build(start, mid - 1, inorder, postorder, ind)
38 | return root
39 |
40 | s = Solution()
41 | print(s.buildTree2([1,2,3,4],[2,4,3,1]))
--------------------------------------------------------------------------------
/leetcode/112. Path Sum.py:
--------------------------------------------------------------------------------
1 | '''
2 | Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum.
3 |
4 | For example:
5 | Given the below binary tree and sum = 22,
6 | 5
7 | / \
8 | 4 8
9 | / / \
10 | 11 13 4
11 | / \ \
12 | 7 2 1
13 | return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22.
14 | '''
15 | # Definition for a binary tree node.
16 | class TreeNode(object):
17 | def __init__(self, x):
18 | self.val = x
19 | self.left = None
20 | self.right = None
21 |
22 | class Solution(object):
23 | def hasPathSum(self, root, sum):
24 | if not root:
25 | return False
26 | if root.val == sum and root.left is None and root.right is None:
27 | return True
28 | return self.hasPathSum(root.left, sum-root.val) or self.hasPathSum(root.right, sum-root.val)
--------------------------------------------------------------------------------
/leetcode/113. Path Sum II.py:
--------------------------------------------------------------------------------
1 | '''
2 | Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum.
3 |
4 | For example:
5 | Given the below binary tree and sum = 22,
6 | 5
7 | / \
8 | 4 8
9 | / / \
10 | 11 13 4
11 | / \ / \
12 | 7 2 5 1
13 | return
14 | [
15 | [5,4,11,2],
16 | [5,8,4,5]
17 | ]
18 | '''
19 |
20 |
21 | # Definition for a binary tree node.
22 | class TreeNode(object):
23 | def __init__(self, x):
24 | self.val = x
25 | self.left = None
26 | self.right = None
27 |
28 | class Solution(object):
29 | def pathSum(self, root, sum):
30 | if not root:
31 | return []
32 | if root.left == None and root.right == None:
33 | if sum == root.val:
34 | return [[root.val]]
35 | else:
36 | return []
37 | stack = []
38 | leftStack = self.pathSum(root.left, sum - root.val)
39 | for i in leftStack:
40 | i.insert(0, root.val)
41 | stack.append(i)
42 | rightStack = self.pathSum(root.right, sum - root.val)
43 | for i in rightStack:
44 | i.insert(0, root.val)
45 | stack.append(i)
46 | return stack
47 |
--------------------------------------------------------------------------------
/leetcode/13. Roman to Integer.py:
--------------------------------------------------------------------------------
1 | # -*- coding:utf-8 -*-
2 | '''
3 | Given a roman numeral, convert it to an integer.
4 |
5 | Input is guaranteed to be within the range from 1 to 3999.
6 |
7 | '''
8 |
9 | class Solution(object):
10 | def romanToInt(self, s):
11 | romanDict = {'M':1000, 'D':500, 'C':100, 'L':50, 'X':10, 'V':5, 'I':1}
12 | res, p = 0, 'I'
13 | for ch in s[::-1]:
14 | if romanDict[ch] < romanDict[p]:
15 | res = res - romanDict[ch]
16 | else:
17 | res = res + romanDict[ch]
18 | p = ch
19 | return res
20 |
21 | s = Solution()
22 | print((s.romanToInt("IX")))
--------------------------------------------------------------------------------
/leetcode/143. Reorder List.py:
--------------------------------------------------------------------------------
1 | '''
2 | Given a singly linked list L: L0→L1→…→Ln-1→Ln,
3 | reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
4 |
5 | You must do this in-place without altering the nodes' values.
6 |
7 | For example,
8 | Given {1,2,3,4}, reorder it to {1,4,2,3}.
9 | '''
10 |
11 |
12 | # Definition for singly-linked list.
13 | class ListNode(object):
14 | def __init__(self, x):
15 | self.val = x
16 | self.next = None
17 |
18 | class Solution(object):
19 | def reorderList(self, head):
20 | if not head or not head.next:
21 | return
22 | ahead, behind = self.split(head)
23 | behind = self.reverse(behind)
24 | head = self.reConnect(ahead, behind)
25 | # split the linkedlist in middle
26 | def split(self, head):
27 | fast = head
28 | slow = head
29 | while fast and fast.next:
30 | slow = slow.next
31 | fast = fast.next
32 | fast = fast.next
33 | middle = slow.next
34 | slow.next = None
35 | return head, middle
36 | # reverse the behind half linkedlist
37 | def reverse(self, head):
38 | reHead = None
39 | curNode = head
40 | while curNode:
41 | nextNode = curNode.next
42 | curNode.next = reHead
43 | reHead = curNode
44 | curNode = nextNode
45 | return reHead
46 | # merge the two linkedlist to one
47 | def reConnect(self, first, second):
48 | head = first
49 | tail = first
50 | first = first.next
51 | while second:
52 | tail.next = second
53 | tail = tail.next
54 | second = second.next
55 | if first:
56 | first, second = second, first
57 | return head
--------------------------------------------------------------------------------
/leetcode/15. 3Sum.py:
--------------------------------------------------------------------------------
1 | '''
2 | Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
3 |
4 | Note: The solution set must not contain duplicate triplets.
5 |
6 | For example, given array S = [-1, 0, 1, 2, -1, -4],
7 |
8 | A solution set is:
9 | [[-1, 0, 1],[-1, -1, 2]]
10 | '''
11 |
12 | class Solution(object):
13 | def threeSum(self, nums):
14 | if nums == None or len(nums) < 3:
15 | return []
16 | elif len(nums) == 3 and sum(nums) == 0:
17 | return [sorted(nums)]
18 |
19 | nums.sort() # sorted, O(nlogn)
20 | result, length = [], len(nums)
21 | for i in range(length - 2):
22 | if i > 0 and nums[i-1] == nums[i]:
23 | continue
24 | l, r = i + 1, length - 1 # i < l < r
25 | while l < r:
26 | Sum = nums[i] + nums[l] + nums[r]
27 | if Sum == 0:
28 | result.append([nums[i], nums[l], nums[r]])
29 | while l < r and nums[l] == nums[l + 1]: # if appear same integer, l move right 1 place
30 | l += 1
31 | while l < r and nums[r] == nums[r - 1]: # if appear same integer, r move left 1 place
32 | r -= 1
33 | if Sum > 0:
34 | r -= 1
35 | else:
36 | l += 1
37 | return result
38 | s = Solution()
39 | print(s.threeSum([0, 0, 0, 0, 0]))
--------------------------------------------------------------------------------
/leetcode/19. Remove Nth Node From End of List.py:
--------------------------------------------------------------------------------
1 | '''
2 | Given a linked list, remove the nth node from the end of list and return its head.
3 | For example,
4 | Given linked list: 1->2->3->4->5, and n = 2.
5 | After removing the second node from the end, the linked list becomes 1->2->3->5.
6 | '''
7 | class ListNode(object):
8 | def __init__(self, x):
9 | self.val = x
10 | self.next = None
11 |
12 | class Solution(object):
13 | def removeNthFromEnd(self, head, n):
14 | if not head and n <= 0:
15 | return None
16 | pNode = ListNode(0)
17 | pNode.next = head
18 | first, second = pNode, pNode
19 | for i in range(n):
20 | if first.next:
21 | first = first.next
22 | else:
23 | return None
24 | while first.next:
25 | first = first.next
26 | second = second.next
27 | second.next = second.next.next
28 | return pNode.next
--------------------------------------------------------------------------------
/leetcode/192.WordFrequency.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | :< 4 -> 3) + (5 -> 6 -> 4)
4 | Output: 7 -> 0 -> 8
5 | '''
6 | class ListNode(object):
7 | def __init__(self, x):
8 | self.val = x
9 | self.next = None
10 |
11 | class Solution(object):
12 | def addTwoNumbers(self, l1, l2):
13 | pNode = ListNode(0)
14 | pHead = pNode
15 | val = 0
16 | while l1 or l2 or val:
17 | if l1:
18 | val += l1.val
19 | l1 = l1.next
20 | if l2:
21 | val += l2.val
22 | l2 = l2.next
23 | pNode.next = ListNode(val % 10)
24 | val /= 10
25 | pNode = pNode.next
26 | return pHead.next
27 |
--------------------------------------------------------------------------------
/leetcode/203. Remove Linked List Elements.py:
--------------------------------------------------------------------------------
1 | '''
2 | Remove all elements from a linked list of integers that have value val.
3 | Example
4 | Given: 1 --> 2 --> 6 --> 3 --> 4 --> 5 --> 6, val = 6
5 | Return: 1 --> 2 --> 3 --> 4 --> 5
6 | '''
7 | # Definition for singly-linked list.
8 | class ListNode(object):
9 | def __init__(self, x):
10 | self.val = x
11 | self.next = None
12 |
13 | class Solution(object):
14 |
15 | def removeElements(self, head, val):
16 | preNode, res = None, head
17 | while head:
18 | if head.val == val:
19 | if not preNode:
20 | res = res.next
21 | else:
22 | preNode.next = head.next
23 | else:
24 | preNode = head
25 | head = head.next
26 | return res
--------------------------------------------------------------------------------
/leetcode/21. Merge Two Sorted Lists.py:
--------------------------------------------------------------------------------
1 | '''
2 | Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.
3 | '''
4 |
5 | # Definition for singly-linked list.
6 | class ListNode(object):
7 | def __init__(self, x):
8 | self.val = x
9 | self.next = None
10 |
11 | class Solution(object):
12 | def mergeTwoLists(self, l1, l2):
13 | if l1 == None or l2 == None:
14 | return l1 or l2
15 | pHead = pNode = ListNode(0)
16 | while l1 and l2:
17 | if l1.val < l2.val:
18 | pNode.next = l1
19 | l1 = l1.next
20 | else:
21 | pNode.next = l2
22 | l2 = l2.next
23 | pNode = pNode.next
24 | pNode.next = l1 or l2
25 | return pHead.next
26 | # recursively
27 | def mergeTwoLists2(self, l1, l2):
28 | if not l1 or not l2:
29 | return l1 or l2
30 | if l1.val < l2.val:
31 | l1.next = self.mergeTwoLists2(l1.next, l2)
32 | return l1
33 | else:
34 | l2.next = self.mergeTwoLists2(l1, l2.next)
35 | return l2
36 |
--------------------------------------------------------------------------------
/leetcode/226. Invert Binary Tree.py:
--------------------------------------------------------------------------------
1 | '''
2 | Invert a binary tree.
3 |
4 | 4
5 | / \
6 | 2 7
7 | / \ / \
8 | 1 3 6 9
9 | to
10 | 4
11 | / \
12 | 7 2
13 | / \ / \
14 | 9 6 3 1
15 | '''
16 |
17 |
18 | # Definition for a binary tree node.
19 | class TreeNode(object):
20 | def __init__(self, x):
21 | self.val = x
22 | self.left = None
23 | self.right = None
24 |
25 | class Solution(object):
26 | def invertTree(self, root):
27 | if not root:
28 | return
29 | if not root.left and not root.right:
30 | return root
31 | root.left, root.right = self.invertTree(root.right), self.invertTree(root.left)
32 | return root
33 |
34 | def invertTree2(self, root):
35 | if root:
36 | root.left, root.right = self.invertTree(root.right), self.invertTree(root.left)
37 | return root
38 | # interative
39 | def invertTreeInter(self, root):
40 | stack = [root]
41 | while stack:
42 | node = stack.pop()
43 | if node:
44 | node.left, node.right = node.right, node.left
45 | stack += node.left, node.right
46 | return root
47 |
--------------------------------------------------------------------------------
/leetcode/230. Kth Smallest Element in a BST.py:
--------------------------------------------------------------------------------
1 | '''
2 | Given a binary search tree, write a function kthSmallest to find the kth smallest element in it.
3 | '''
4 | # Definition for a binary tree node.
5 | class TreeNode(object):
6 | def __init__(self, x):
7 | self.val = x
8 | self.left = None
9 | self.right = None
10 |
11 | class Solution(object):
12 | def kthSmallest(self, pRoot, k):
13 | if k <= 0 or not pRoot:
14 | return None
15 | treeStack, nodesQue = [], []
16 | pNode = pRoot
17 | while pNode or len(treeStack):
18 | while pNode:
19 | treeStack.append(pNode)
20 | pNode = pNode.left
21 | if len(treeStack):
22 | pNode = treeStack.pop()
23 | nodesQue.append(pNode)
24 | pNode = pNode.right
25 | if k > len(nodesQue):
26 | return None
27 | return nodesQue[k-1].val
--------------------------------------------------------------------------------
/leetcode/239. Sliding Window Maximum.py:
--------------------------------------------------------------------------------
1 | '''
2 | Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position.
3 |
4 | For example,
5 | Given nums = [1,3,-1,-3,5,3,6,7], and k = 3.
6 |
7 | Window position Max
8 | --------------- -----
9 | [1 3 -1] -3 5 3 6 7 3
10 | 1 [3 -1 -3] 5 3 6 7 3
11 | 1 3 [-1 -3 5] 3 6 7 5
12 | 1 3 -1 [-3 5 3] 6 7 5
13 | 1 3 -1 -3 [5 3 6] 7 6
14 | 1 3 -1 -3 5 [3 6 7] 7
15 | Therefore, return the max sliding window as [3,3,5,5,6,7].
16 | '''
17 | class Solution(object):
18 | def maxSlidingWindow(self, nums, k):
19 | if not nums or k <= 0:
20 | return []
21 | '''
22 | if you want to modify time complexity, you can write below:
23 | from collections import deque
24 | res, queue = [], deque()
25 | and replace queue.pop(0) with queue.popleft()
26 | '''
27 | res, queue = [], []
28 | for ind, val in enumerate(nums):
29 | if queue and queue[0] <= ind - k:
30 | queue.pop(0)
31 | while queue and nums[queue[-1]] < val:
32 | queue.pop()
33 | queue.append(ind)
34 | if ind + 1 >= k:
35 | res.append(nums[queue[0]])
36 | return res
37 |
38 | s = Solution()
39 | print(s.maxSlidingWindow([1,3,-1,-3,5,3,6,7], 3))
--------------------------------------------------------------------------------
/leetcode/24. Swap Nodes in Pairs.py:
--------------------------------------------------------------------------------
1 | '''
2 | Given a linked list, swap every two adjacent nodes and return its head.
3 |
4 | For example,
5 | Given 1->2->3->4, you should return the list as 2->1->4->3.
6 |
7 | Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be changed.
8 | '''
9 |
10 | class ListNode(object):
11 | def __init__(self, x):
12 | self.val = x
13 | self.next = None
14 |
15 | class Solution(object):
16 | def swapPairs(self, head):
17 | if head == None or head.next == None:
18 | return head
19 | cur = head
20 | head = head.next
21 | while cur and cur.next:
22 | pNext = cur.next.next
23 | cur.next.next = cur
24 | if pNext:
25 | if pNext.next:
26 | cur.next = pNext.next
27 | else:
28 | cur.next = pNext
29 | else:
30 | cur.next = None
31 | cur = pNext
32 | return head
33 | # recursion
34 | def swapPairs2(self, head):
35 | if not head or not head.next:
36 | return head
37 |
38 | first, second = head, head.next
39 | third = second.next
40 | head = second
41 | second.next = first
42 | first.next = self.swapPairs(third)
43 | return head
--------------------------------------------------------------------------------
/leetcode/292. Nim Game.py:
--------------------------------------------------------------------------------
1 | '''
2 | You are playing the following Nim Game with your friend: There is a heap of stones on the table, each time one of you take turns to remove 1 to 3 stones. The one who removes the last stone will be the winner. You will take the first turn to remove the stones.
3 |
4 | Both of you are very clever and have optimal strategies for the game. Write a function to determine whether you can win the game given the number of stones in the heap.
5 |
6 | For example, if there are 4 stones in the heap, then you will never win the game: no matter 1, 2, or 3 stones you remove, the last stone will always be removed by your friend.
7 | '''
8 |
9 | class Solution(object):
10 | def canWinNim(self, n):
11 | return True if n%4 != 0 else False
12 | # return bool(n%4)
--------------------------------------------------------------------------------
/leetcode/297. Serialize and Deserialize Binary Tree.py:
--------------------------------------------------------------------------------
1 | '''
2 | Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment.
3 |
4 | Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure.
5 |
6 | For example, you may serialize the following tree
7 |
8 | 1
9 | / \
10 | 2 3
11 | / \
12 | 4 5
13 | as "[1,2,3,null,null,4,5]"
14 | '''
15 | # Definition for a binary tree node.
16 | class TreeNode(object):
17 | def __init__(self, x):
18 | self.val = x
19 | self.left = None
20 | self.right = None
21 |
22 | class Codec:
23 | def serialize(self, root):
24 | if not root:
25 | return 'None'
26 | stack, seriStr = [], ""
27 | while root or stack:
28 | while root:
29 | seriStr += str(root.val) + ','
30 | stack.append(root)
31 | root = root.left
32 | seriStr += 'None,'
33 | root = stack.pop()
34 | root = root.right
35 | seriStr = seriStr[:-1]
36 | return seriStr
37 |
38 | def deserialize(self, data):
39 | serialize = data.split(',')
40 | tree, sp = self.bulidTree(serialize, 0)
41 | return tree
42 |
43 | def bulidTree(self, s, sp):
44 | if sp >= len(s) or s[sp] == 'None':
45 | return None, sp + 1
46 | node = TreeNode(int(s[sp]))
47 | sp += 1
48 | node.left, sp = self.bulidTree(s, sp)
49 | node.right, sp = self.bulidTree(s, sp)
50 | return node, sp
--------------------------------------------------------------------------------
/leetcode/3. Longest Substring Without Repeating Characters.py:
--------------------------------------------------------------------------------
1 | '''
2 | Given a string, find the length of the longest substring without repeating characters.
3 |
4 | Examples:
5 |
6 | Given "abcabcbb", the answer is "abc", which the length is 3.
7 |
8 | Given "bbbbb", the answer is "b", with the length of 1.
9 |
10 | Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequence and not a substring.
11 | '''
12 |
13 | class Solution(object):
14 | def lengthOfLongestSubstring(self, s):
15 | if s == None or len(s) <= 0:
16 | return
17 | # charDict存储每个字符以及字符出现的最后的位置, res为当前最长的的子串长度, st当前无重复子串的最左边字符的位置
18 | charDict, res, st = {}, 0, 0
19 | for i, ch in enumerate(s):
20 | if ch not in charDict or charDict[ch] < st:
21 | res = max(res, i - st + 1)
22 | else:
23 | st = charDict[ch] + 1
24 | charDict[ch] = i
25 | return res
26 |
27 | s = Solution()
28 | print(s.lengthOfLongestSubstring('pwwkew'))
--------------------------------------------------------------------------------
/leetcode/300. Longest Increasing Subsequence.py:
--------------------------------------------------------------------------------
1 | # -*- coding:utf-8 -*-
2 | '''
3 | Given an unsorted array of integers, find the length of longest increasing subsequence.
4 |
5 | For example,
6 | Given [10, 9, 2, 5, 3, 7, 101, 18],
7 | The longest increasing subsequence is [2, 3, 7, 101], therefore the length is 4. Note that there may be more than one LIS combination, it is only necessary for you to return the length.
8 |
9 | Your algorithm should run in O(n^2) complexity.
10 |
11 | Follow up: Could you improve it to O(n log n) time complexity?
12 | '''
13 |
14 |
15 | class Solution(object):
16 | # 原始O(nlogn)方法
17 | def lengthOfLIS(self, nums):
18 | tails = [0] * len(nums)
19 | size = 0
20 | for x in nums:
21 | i, j = 0, size
22 | while i != j:
23 | mid = (i + j) // 2
24 | if tails[mid] < x:
25 | i = mid + 1
26 | else:
27 | j = mid
28 | tails[i] = x
29 | size = max(i + 1, size)
30 | return size
31 | # 简单优化的O(nlogn)方法, 1000000长度为8的数据平均节约0.5s
32 | def lengthOfLIS2(self, nums):
33 | tails = [0] * len(nums)
34 | size = 0
35 | for x in nums:
36 | i, j = 0, size
37 | if j > 0 and tails[j - 1] < x:
38 | tails[j] = x
39 | size += 1
40 | continue
41 | while i != j:
42 | mid = (i + j) // 2
43 | if tails[mid] < x:
44 | i = mid + 1
45 | else:
46 | j = mid
47 | tails[i] = x
48 | size = max(i + 1, size)
49 | return size
50 |
51 | s = Solution()
52 | aList = [3, 2, 4, 9, 10, 22, 15, 17, 23, 6]
53 | print(s.lengthOfLIS(aList), s.lengthOfLIS2(aList))
--------------------------------------------------------------------------------
/leetcode/322. Coin Change:
--------------------------------------------------------------------------------
1 | '''
2 | You are given coins of different denominations and a total amount of money amount. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.
3 |
4 | Example 1:
5 | coins = [1, 2, 5], amount = 11
6 | return 3 (11 = 5 + 5 + 1)
7 |
8 | Example 2:
9 | coins = [2], amount = 3
10 | return -1.
11 |
12 | Note:
13 | You may assume that you have an infinite number of each kind of coin.
14 | '''
15 | class Solution(object):
16 | def coinChange(self, coins, amount):
17 | #corner cases
18 | if amount == 0:
19 | return 0
20 | if len(coins) == 1 and coins[0] > amount:
21 | return -1
22 | dp = [-1 for i in range(amount + 1)]
23 | for i in range(1, amount + 1):
24 | # if the value matches the coin
25 | if i in coins:
26 | dp[i] = 1
27 | else:
28 | minV = sys.maxsize
29 | # since the size of coins are much less than the amount,
30 | # we check if for every coin there could be a solution and find the minimum of that
31 | for j in coins:
32 | remain = i - j
33 | # -1 means there is no solution, so we don't need to check if dp[i] is -1
34 | if remain > 0 and dp[remain] != -1:
35 | minV = min(minV, dp[remain])
36 | if minV ==sys.maxsize:
37 | dp[i] = -1
38 | else:
39 | dp[i] = minV + 1
40 | return dp[-1]
41 |
42 |
--------------------------------------------------------------------------------
/leetcode/337. House Robber III:
--------------------------------------------------------------------------------
1 | '''
2 | The thief has found himself a new place for his thievery again. There is only one entrance to this area, called the "root." Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that "all houses in this place forms a binary tree". It will automatically contact the police if two directly-linked houses were broken into on the same night.
3 |
4 | Determine the maximum amount of money the thief can rob tonight without alerting the police.
5 |
6 | Example 1:
7 | 3
8 | / \
9 | 2 3
10 | \ \
11 | 3 1
12 | Maximum amount of money the thief can rob = 3 + 3 + 1 = 7.
13 | Example 2:
14 | 3
15 | / \
16 | 4 5
17 | / \ \
18 | 1 3 1
19 | Maximum amount of money the thief can rob = 4 + 5 = 9.
20 | '''
21 | # Definition for a binary tree node.
22 | # class TreeNode(object):
23 | # def __init__(self, x):
24 | # self.val = x
25 | # self.left = None
26 | # self.right = None
27 |
28 | class Solution(object):
29 | def rob(self, root):
30 | def gain(root):
31 | if root == None:
32 | return 0
33 | o1 = root.val
34 | if o1 < 0:
35 | return -o1
36 | if root.left:
37 | o1 += gain(root.left.left) + gain(root.left.right)
38 | if root.right:
39 | o1 += gain(root.right.left) + gain(root.right.right)
40 | o2 = gain(root.left) + gain(root.right)
41 | o = max(o1,o2)
42 | root.val = -1*o
43 | return o
44 | return gain(root)
45 |
--------------------------------------------------------------------------------
/leetcode/344. Reverse String.py:
--------------------------------------------------------------------------------
1 | '''
2 | Write a function that takes a string as input and returns the string reversed.
3 |
4 | Example:
5 | Given s = "hello", return "olleh".
6 | '''
7 |
8 | class Solution(object):
9 | def reverseString(self, s):
10 | return s[::-1]
11 | def reverseString2(self, s):
12 | if not s or len(s) < 2:
13 | return s
14 | slist = list(s)
15 | start, end = 0, len(s)-1
16 | while start < end:
17 | slist[start], slist[end] = slist[end], slist[start]
18 | start += 1
19 | end -= 1
20 | return "".join(slist)
21 |
22 | s = Solution()
23 | print(s.reverseString("hello"))
--------------------------------------------------------------------------------
/leetcode/4. Median of Two Sorted Arrays:
--------------------------------------------------------------------------------
1 | '''
2 | There are two sorted arrays nums1 and nums2 of size m and n respectively.
3 |
4 | Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
5 |
6 | Example 1:
7 | nums1 = [1, 3]
8 | nums2 = [2]
9 |
10 | The median is 2.0
11 | Example 2:
12 | nums1 = [1, 2]
13 | nums2 = [3, 4]
14 |
15 | The median is (2 + 3)/2 = 2.5
16 | '''
17 | class Solution(object):
18 | def findMedianSortedArrays(self, a, b):
19 | n = len(a)+len(b)
20 | if n&1:
21 | return self.kthSmallest(a,b,n//2+1)
22 | else:
23 | return (self.kthSmallest(a,b,n//2+1) + self.kthSmallest(a,b,n//2))/2.0
24 |
25 | def kthSmallest(self,a,b,k):
26 | if len(a)+len(b) < k:
27 | return None
28 | i=0
29 | j=0
30 | flag = True
31 | while k>0:
32 | if i >= len(a):
33 | j+=1
34 | flag = False
35 | elif j >= len(b):
36 | i+=1
37 | flag = True
38 | elif a[i] <= b[j]:
39 | i+=1
40 | flag = True
41 | elif a[i] > b[j]:
42 | j+=1
43 | flag = False
44 | k-=1
45 |
46 | if flag:
47 | return a[i-1]
48 | else:
49 | return b[j-1]
50 |
--------------------------------------------------------------------------------
/leetcode/5. Longest Palindromic Substring.py:
--------------------------------------------------------------------------------
1 | '''
2 | Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.
3 | '''
4 |
5 | # 使用manacher算法进行字长回文串的判断
6 | class Solution(object):
7 | def longestPalindrome(self, s):
8 | if s == None or len(s) <= 0:
9 | return
10 | newS = '#' + '#'.join(s) + '#'
11 |
12 | length, center, rightMost, maxCenter, maxLen, i = len(newS), 0, 0, 0, 0, 0
13 | pArr = [0] * length
14 | for i in range(length):
15 | pArr[i] = 1 if rightMost < i else min(rightMost-i, pArr[(center << 1) - i])
16 | while i + pArr[i] < length and i - pArr[i] > -1 and newS[i + pArr[i]] == newS[i - pArr[i]]:
17 | pArr[i] += 1
18 | if i + pArr[i] > rightMost:
19 | center = i
20 | rightMost = i + pArr[i]
21 | if pArr[i] > maxLen:
22 | maxLen = pArr[i]
23 | maxCenter = i
24 | start = (maxCenter - maxLen + 1) >> 1
25 | return s[start: start + maxLen - 1]
26 |
27 | def manacher(s):
28 | # 预处理
29 | s = '#' + '#'.join(s) + '#'
30 |
31 | RL = [0] * len(s)
32 | MaxRight = 0
33 | pos = 0
34 | MaxLen = 0
35 | for i in range(len(s)):
36 | if i < MaxRight:
37 | RL[i] = min(RL[2 * pos - i], MaxRight - i)
38 | else:
39 | RL[i] = 1
40 | # 尝试扩展,注意处理边界
41 | while i - RL[i] >= 0 and i + RL[i] < len(s) and s[i - RL[i]] == s[i + RL[i]]:
42 | RL[i] += 1
43 | # 更新MaxRight,pos
44 | if RL[i] + i - 1 > MaxRight:
45 | MaxRight = RL[i] + i - 1
46 | pos = i
47 | # 更新最长回文串的长度
48 | MaxLen = max(MaxLen, RL[i])
49 | return MaxLen - 1
50 |
51 | test = 'aaaba'
52 | s = Solution()
53 | print(s.longestPalindrome(test))
--------------------------------------------------------------------------------
/leetcode/61. Rotate List:
--------------------------------------------------------------------------------
1 | '''
2 | Given a list, rotate the list to the right by k places, where k is non-negative.
3 |
4 | For example:
5 | Given 1->2->3->4->5->NULL and k = 2,
6 | return 4->5->1->2->3->NULL.
7 | '''
8 | # Definition for singly-linked list.
9 | class ListNode(object):
10 | def __init__(self, x):
11 | self.val = x
12 | self.next = None
13 |
14 | class Solution(object):
15 | def rotateRight(self, head, k):
16 | ref = head
17 | length = 0
18 |
19 | while head:
20 | head = head.next
21 | length += 1
22 |
23 | if length < 2 or k % length == 0:
24 | return ref
25 |
26 | prev = None
27 | current = ref
28 | for _ in xrange(length - (k % length)):
29 | prev, current = current, current.next
30 |
31 | prev.next = None
32 | new_head = current
33 |
34 | if not current:
35 | return ref
36 | while current.next:
37 | current = current.next
38 | current.next = ref
39 |
40 | return new_head
41 |
--------------------------------------------------------------------------------
/leetcode/67. AddBinary.py:
--------------------------------------------------------------------------------
1 | '''
2 | Given two binary strings, return their sum (also a binary string).
3 | For example,
4 | a = "11"
5 | b = "1"
6 | Return "100".
7 | '''
8 | class Solution(object):
9 | def addBinary(self, a, b):
10 | lenA, lenB = len(a), len(b)
11 | a, b = list(a), list(b)
12 | if lenA == 0:
13 | return b
14 | if lenB == 0:
15 | return a
16 | carry, r = 0, ['']*(max(lenA, lenB)+1)
17 | for i in range(len(r)):
18 | p1, p2 = 0, 0
19 | if i < lenA:
20 | p1 = int(a[lenA-1-i])
21 | if i < lenB:
22 | p2 = int(b[lenB-1-i])
23 | sum = p1 + p2 + carry
24 | r[len(r)-1-i] = str(sum%2)
25 | carry = sum // 2
26 | return str(int("".join(r)))
27 | s = Solution()
28 | print(s.addBinary('10110', '101'))
--------------------------------------------------------------------------------
/leetcode/82. Remove Duplicates from Sorted List II.py:
--------------------------------------------------------------------------------
1 | '''
2 | Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.
3 |
4 | For example,
5 | Given 1->2->3->3->4->4->5, return 1->2->5.
6 | Given 1->1->1->2->3, return 2->3.
7 | '''
8 | # -*- coding:utf-8 -*-
9 | class ListNode:
10 | def __init__(self, x):
11 | self.val = x
12 | self.next = None
13 | class Solution:
14 | def deleteDuplication(self, head):
15 | dummy = pre = ListNode(0)
16 | dummy.next = head
17 | while head and head.next:
18 | if head.val == head.next.val:
19 | while head and head.next and head.val == head.next.val:
20 | head = head.next
21 | head = head.next
22 | pre.next = head
23 | else:
24 | pre = pre.next
25 | head = head.next
26 | return dummy.next
--------------------------------------------------------------------------------
/leetcode/83. Remove Duplicates from Sorted List.py:
--------------------------------------------------------------------------------
1 | '''
2 | Given a sorted linked list, delete all duplicates such that each element appear only once.
3 |
4 | For example,
5 | Given 1->1->2, return 1->2.
6 | Given 1->1->2->3->3, return 1->2->3.
7 | '''
8 |
9 | # Definition for singly-linked list.
10 | class ListNode(object):
11 | def __init__(self, x):
12 | self.val = x
13 | self.next = None
14 |
15 | class Solution(object):
16 | def deleteDuplicates(self, head):
17 | pNode = head
18 | while pNode:
19 | while pNode.next and pNode.next.val == pNode.val:
20 | pNode.next = pNode.next.next
21 | pNode = pNode.next
22 | return head
--------------------------------------------------------------------------------
/leetcode/words.txt:
--------------------------------------------------------------------------------
1 | the day is sunny
2 | the the the sunny is is
--------------------------------------------------------------------------------
/mysingleton.py:
--------------------------------------------------------------------------------
1 | # 单例模式
2 | class My_Singleton(object):
3 | def foo(self):
4 | pass
5 | my_singleton = My_Singleton()
--------------------------------------------------------------------------------
/regularExpression/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/regularExpression/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/regularExpression/.idea/regularExpression.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/regularExpression/README.md:
--------------------------------------------------------------------------------
1 | # 正则表达式
2 | 1. 使用单个字符串来描述匹配一系列符合某个句法规则的字符串。
3 | 2. 是对字符串操作的一种逻辑公式
4 | 3. 应用场景:处理文本和数据
5 | 4. 正则表达式过程:依次拿出表达式和文本中的字符比较,如果每一个字符都能匹配, 则匹配成功;否则匹配失败。
6 |
7 | ## Python下使用正则表达式
8 | 1. `import re`:正则表达式模块:Python通过re模块提供对正则表达式的支持。使用re的一般步骤是先将正则表达式的字符串形式编译为Pattern实例,然后使用Pattern实例处理文本并获得匹配结果(一个Match实例),最后使用Match实例获得信息,进行其他的操作。r代表进行匹配的是元字符串, 不使用元字符串则需要注意转译的情况。
9 |
10 | 使用正则表达式匹配字符串开头是否为指定的字符或字符串:
11 |
12 |
13 | ```
14 | import re
15 | str1 = 'test python'
16 | # 将正则表达式编译成pattern对象
17 | # 使用r'test', r代表进行匹配的是元字符串
18 | pa = re.compile(r'test') # pa已经成为一个pattern实例
19 | print(type(pa))
20 |
21 | ma = pa.match(str1) # 若匹配成功, ma成为一个match对象
22 |
23 | print(ma)
24 | print(ma.group()) # group()返回一个str或者tuple
25 | print(ma.span()) # 返回字符串的索引
26 | print(ma.re) # pattern的实例
27 | ```
28 |
29 | ```
30 | # 返回结果
31 |
32 | <_sre.SRE_Match object; span=(0, 4), match='test'>
33 | test
34 | (0, 4)
35 | re.compile('test')
36 | ```
37 |
38 | ## 正则表达式语法
39 |
40 |
41 | |字符|匹配|
42 | |------|------|
43 | |.|匹配任意字符(除了\n)|
44 | |[...]|匹配字符集|
45 | |\d / \D|匹配数字/非数字|
46 | |\s / \S|匹配空白/非空白字符|
47 | |\w / \W|匹配单词字符[a-zA-Z0-9]/非单词字符|
48 | |\*|匹配前一个字符0次或者无限次|
49 | |+|匹配前一个字符1次或者无限次|
50 | |?|匹配前一个字符0次或1次|
51 | |{m}/{m,n}|匹配前一个字符m次或者n次|
52 | |{m,}|匹配前一个字符m次或更多次|
53 | |\*? / +? / ??|匹配模式变为非贪婪(尽可能少匹配字符|)
54 | |^|匹配字符串开头|
55 | |$|匹配字符串结尾|
56 | |\A / \Z|指定的字符串匹配必须出现在开头/结尾|
57 | |\||匹配左右任意一个表达式|
58 | |(ab)|括号中表达式作为一个分组|
59 | |\\\|引用编号为num的分组匹配到的字符串|
60 | |(?P\)|分组起一个别名|
61 | |(?P=name)|引用别名为name的分组匹配字符串|
62 |
63 | ## Python正则表达式--re模块其他方法
64 | 1. search(pattern, string, flags=0)在一个字符串中查找匹配
65 | 2. findall(pattern, string, flags=0)找到匹配,返回所有匹配部分的列表
66 | 3. sub(pattern, repl, string, count=0, flags=0)将字符串中匹配正则表达式的部分替换为其它值
67 | 4. split(pattern, string, maxsplit=0, flags=0)根据匹配分割字符串, 返回分割字符串组成的列表
68 |
69 | ## re练习
70 | 利用正则表达式尝试抓取了20160711[腾讯网](http://www.qq.com/)上的jpg和png图像。
--------------------------------------------------------------------------------
/regularExpression/reTest.py:
--------------------------------------------------------------------------------
1 | str1 = 'test python'
2 | # 未使用正则表达式的查找
3 | print(str1.find('1'))
4 | print(str1.find('test'))
5 | print(str1.startswith('test'))
6 |
7 | # 使用正则表达式查找
8 | import re
9 | # 将正则表达式编译成pattern对象
10 | # 使用r'test', r代表进行匹配的是元字符串
11 | pa = re.compile(r'test') # pa已经成为一个pattern实例
12 | print(type(pa))
13 |
14 | ma = pa.match(str1) # 若匹配成功, ma成为一个match对象
15 |
16 | print(ma)
17 | print(ma.group()) # group()返回一个str或者tuple
18 | print(ma.span()) # 返回字符串的索引
19 | print(ma.re) # pattern的实例
20 |
21 | # 另一个例子
22 | pa2 = re.compile(r'_')
23 | ma2 = pa2.match('_value')
24 |
25 | print(ma2.group())
26 |
27 | # 例子3
28 | pa3 = re.compile(r'_')
29 | ma3 = pa3.match('value_')
30 | # print(ma3.group()) #匹配失败 'NoneType' object has no attribute 'group'
31 |
32 | # 忽略大小写匹配
33 | pa = re.compile(r'test', re.I) # re.I 忽略大小写, I=ignore
34 | print(pa)
35 |
36 | ma = pa.match('Test python')
37 | print(ma.group())
38 |
39 | #
40 | ma = re.match(r'test', 'Test Python', re.I)
41 | print(ma.group())
--------------------------------------------------------------------------------
/regularExpression/re模块其他方法.py:
--------------------------------------------------------------------------------
1 | import re
2 |
3 | str1 = 'study time = 1000'
4 |
5 | print(str1.find('1000'))
6 |
7 | # 如果数字1000发生变化, 可以使用正则表达式的search查找数组, 其中\d+就是匹配任意多字符的数字
8 | # search仅能查找第一个符合项
9 | info = re.search(r'\d+', str1)
10 | print(info.group())
11 |
12 | str1 = 'study time = 10000'
13 | info = re.search(r'\d+', str1)
14 | print(info.group())
15 |
16 | # findall 能查找到所有匹配项, 返回值为一个list
17 | str2 = 'python code num = 100, swift code num = 50, c++ code num = 10'
18 | info = re.findall(r'\d+', str2)
19 | print(info)
20 | print(sum([int(x) for x in info]))
21 |
22 | # sub将字符中匹配正则表达式的部分替换为其它值
23 | str3 = 'python num = 1000'
24 | info = re.sub(r'\d+', '1001', str3) # 将str3中的数字替换为1001
25 | print(info)
26 |
27 | # 利用函数将str3中的数字加1
28 | def add(match):
29 | val = match.group()
30 | num = int(val) + 1
31 | return str(num)
32 |
33 | info = re.sub(r'\d+', add, str3)
34 | print(info)
35 |
36 | # split
37 | str4 = 'class=C C++ Java Python, C#'
38 | info = re.split(r'=| |,', str4)
39 | print(info)
--------------------------------------------------------------------------------
/regularExpression/re练习.py:
--------------------------------------------------------------------------------
1 | '''
2 | 抓取腾讯主页中的图片到本地
3 | 1. 抓取网页
4 | 2. 抓取图片地址
5 | 3. 抓取图片内容并保存到本地
6 | '''
7 |
8 |
9 | import requests
10 | def getdata():
11 | url = 'http://www.qq.com/'
12 | buf = requests.get(url)
13 | return buf
14 |
15 | buf = getdata()
16 |
17 | import re
18 | from numpy import *
19 |
20 | # 抓取png和jpg图像
21 | listurl1 = re.findall(r'src="http://.*\.png', buf.text)
22 | listurl2 = re.findall(r'src="http://.*\.jpg', buf.text)
23 | listURL = []
24 |
25 | # 去除url上不必要的前缀
26 | for url in listurl1:
27 | listURL.append(re.findall(r'http:.*\.png', url))
28 | for url in listurl2:
29 | listURL.append(re.findall(r'http:.*\.jpg', url))
30 |
31 | # 将网上图片写入本地
32 | i = 0
33 | for url in listURL:
34 | f = open(str(i)+'.png', 'wb')
35 | buf = requests.get(url[0], stream=True)
36 | for chunk in buf.iter_content(chunk_size=1024):
37 | if chunk:
38 | f.write(chunk)
39 | f.flush()
40 | f.close()
41 | i += 1
--------------------------------------------------------------------------------
/regularExpression/正则表达式语法.py:
--------------------------------------------------------------------------------
1 | import re
2 |
3 | ma = re.match(r'a', 'a')
4 | print(ma.group())
5 |
6 | # 使用 '.' 匹配任意字符
7 | ma = re.match(r'.', 'b')
8 | print(ma.group())
9 |
10 | ma = re.match(r'{.}', '{a}') # 匹配大括号中的任意一个字符
11 | print(ma.group())
12 |
13 | ma = re.match(r'{..}', '{ab}') # 匹配大括号中的任意两个字符
14 | print(ma.group())
15 |
16 | # 使用 [...] 匹配字符集
17 | ma = re.match(r'{[abc]}', '{a}') # 匹配大括号中为a或b或c的值
18 | print(ma.group())
19 |
20 | ma = re.match(r'{[a-z]}', '{d}') # 匹配a-z的任意一个字符
21 | print(ma.group())
22 |
23 | ma = re.match(r'{[a-zA-Z]}', '{Z}')
24 | print(ma.group())
25 |
26 | ma = re.match(r'{[\w]}', '{0}') # 使用`\w`匹配a-zA-Z0-9的任意一个字符
27 | print(ma.group())
28 |
29 | # 对于中括号中的匹配, 需要加一个转意
30 | ma = re.match(r'\[[\w]\]', '[a]') # '\['和'\]'用来转意
31 | print(ma.group())
32 |
33 | ma = re.match(r'[A-Z][a-z]', 'Aa')
34 | print(ma.group())
35 |
36 | ma = re.match(r'[A-Z][a-z]*', 'A') # 匹配一个大写字母和0个或无穷多个小写字母
37 | print(ma.group())
38 | ma = re.match(r'[A-Z][a-z]*', 'Aa')
39 | print(ma.group())
40 | ma = re.match(r'[A-Z][a-z]*', 'Aafdsfdsb')
41 | print(ma.group())
42 | ma = re.match(r'[A-Z][a-z]*', 'Aafdsfdsbadfas154154') # 此例子只匹配数字前的字符
43 | print(ma.group())
44 |
45 | # 匹配以至少一个为_或者a-z或者A-Z开头的字符, 后面接无线多个_或者a-z或者A-Z。可以用于检测变量名是否合法
46 | # 注意这里 + 代表的是匹配前一个字符1次或者无限次
47 | ma = re.match(r'[_a-zA-Z]+[_\w]*', '__init')
48 | print(ma.group())
49 |
50 | ma = re.match(r'[1-9]?[0-9]', '99') # 按照正常显示0-99的匹配, 09匹配不上, 9可以匹配上。?代表匹配一次或者0次
51 | print(ma.group())
52 |
53 | ma = re.match(r'[1-9]?[0-9]', '09') # 返回 0 , 不是09
54 | print(ma.group())
55 |
56 | ma = re.match(r'[a-zA-Z0-9]{6}', 'bac123') # a-zA-Z0-9匹配六次
57 | print(ma.group())
58 | # ma = re.match(r'[a-zA-Z0-9]{6}', 'bac12') # 返回空, 因为bac12长度小于6
59 | # print(ma.group())
60 | ma = re.match(r'[a-zA-Z0-9]{6}', 'bac1234') # bac123
61 | print(ma.group())
62 |
63 | # 长度为6的163邮箱匹配
64 | ma = re.match(r'[a-zA-Z0-9]{6}@163.com', 'abc123@163.com')
65 | print(ma.group())
66 | # 程度为6-10的163邮箱匹配
67 | ma = re.match(r'[a-zA-Z0-9]{6,10}@163.com', 'abc123gd@163.com')
68 | print(ma.group())
69 |
70 | ma = re.match(r'[0-9][a-z]*?', '1bc') # 只匹配第一个1, 采取非贪婪模式, 尽可能少匹配
71 | print(ma.group())
72 |
73 | ma = re.match(r'[0-9][a-z]+?', '1bc') # 1b
74 | print(ma.group())
75 |
76 | # 匹配字符串的开头或者结尾
77 | ma = re.match(r'[\w]{4,10}@163.com', 'abc123gd@163.comabc') # abc123gd@163.com 但是原始字符串不是我们想要的
78 | print(ma.group())
79 | # ma = re.match(r'[\w]{4,10}@163.com$', 'abc123gd@163.comabc') # 报错, 加上$后, 结尾必须是@163.com
80 | # print(ma.group())
81 |
82 | ma = re.match(r'^[\w]{4,10}@163.com$', 'abc123gd@163.com') # 前面加上 ^ , 必须以[\w]开头
83 | print(ma.group())
84 |
85 |
86 | ma = re.match(r'\Aabc[\w]{4,10}@163.com$', 'abc123gd@163.com') # \A 限定了开头必须以 abc 开头
87 | print(ma.group())
--------------------------------------------------------------------------------
/regularExpression/正则表达式语法2.py:
--------------------------------------------------------------------------------
1 | import re
2 | # | 匹配左右任意一个表达式
3 | ma = re.match(r'abc|d', 'abc')
4 | print(ma.group())
5 | ma = re.match(r'abc|d', 'd')
6 | print(ma.group())
7 |
8 | # 匹配0-99的任意字符串
9 | ma = re.match(r'[1-9]?\d$', '99')
10 | print(ma.group())
11 | # 匹配0-100的任意字符串
12 | ma = re.match(r'[1-9]?\d$|100', '100')
13 | print(ma.group())
14 |
15 | # 匹配一个163或者126的邮箱
16 | ma = re.match(r'[\w]{4,6}@(163|126).com', 'abc89@126.com')
17 | print(ma.group())
18 |
19 | # 匹配
20 | ma = re.match(r'<[\w]+>', '')
21 | print(ma.group())
22 | ma = re.match(r'<([\w]+>)', '') # ()括住的是一个分组, 使用时注意是groups()而不是group()
23 | print(ma.groups())
24 | ma = re.match(r'<([\w]+>)\1', 'book>') # 匹配 book>book> 的第一个分组, 下面写的时候又是group()而不是groups()
25 | print(ma.group())
26 | # 匹配一个python
27 | # <([\w]+>)[\w]+\1 中, 第一个<就是第一个左尖括号, ([\w]+>)表示匹配任意多次 [\w]+>, 这些任意多次 [\w]+> 组成一个元组
28 | # [\w]+ 分为两部分, [\w]+ 表示任意多次 \w, 即这里的 python 字符串, 然后再匹配 <\
29 | # 最后 \1 匹配第一个分组, 即 ([\w]+>) 所对应的内容, 即 book>
30 | ma = re.match(r'<([\w]+>)[\w]+\1', 'python')
31 | print(ma.group())
32 |
33 | # ?P 是给分组起的名字, (?P=mark) 引用名称为mark的分组
34 | ma = re.match(r'<(?P[\w]+>)[\w]+(?P=mark)', 'python')
35 | print(ma.group())
--------------------------------------------------------------------------------
/数据结构.mobi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jack-Lee-Hiter/AlgorithmsByPython/78d7ac4d93db9da40601a5567350bfb3e97e7d46/数据结构.mobi
--------------------------------------------------------------------------------