├── .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 | 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 | ![equation](https://latex.codecogs.com/gif.latex?%5Carg%20%5C%20%5Cmax_%7Bw%2Cb%7D%20%5C%7B%5Cmin_%7Bn%7D%5C%28label*%28%5Cmathit%7B%5Cmathbf%7Bw%5ETx%7D%7D+b%29%29*%5Cfrac%7B1%7D%7B%7C%7C%5Cmathbf%7Bw%7D%7C%7C%7D%29%5C%7D) -------------------------------------------------------------------------------- /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 | 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]+)表示匹配任意多次 [\w]+>, 这些任意多次 [\w]+> 组成一个元组 28 | # [\w]+) 所对应的内容, 即 book> 30 | ma = re.match(r'<([\w]+>)[\w]+python') 31 | print(ma.group()) 32 | 33 | # ?P 是给分组起的名字, (?P=mark) 引用名称为mark的分组 34 | ma = re.match(r'<(?P[\w]+>)[\w]+python') 35 | print(ma.group()) -------------------------------------------------------------------------------- /数据结构.mobi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack-Lee-Hiter/AlgorithmsByPython/78d7ac4d93db9da40601a5567350bfb3e97e7d46/数据结构.mobi --------------------------------------------------------------------------------