leetcode python
31.从1到n的整数中1出现的个数比如,1-13中,1出现6次,分别是1,10,11,12,13。class Solution: def NumberOf1Between1AndN_Solution(self, n): count = 0 for i in range(1,n+1): j = i while j > 0: if j%10 == 1: count += 1 j = j/10 return count 32.把数组排成最小的数输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。思路: 根据题目的要求,两个数字m和n能拼接称数字mn和nm。如果mn<nm,也就是m应该拍在n的前面,我们定义此时m小于n;反之,如果nm<mn,我们定义n小于m。如果mn=nm,m等于n。class Solution: def PrintMinNumber(self, numbers): if not len(numbers): return "" arr = [str(x) for x in numbers] arr.sort(lambda x,y:cmp(x+y,y+x)) return int("".join(arr)) 33.丑数把只包含质因子2、3和5的数称作丑数。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。思路:动态规划的解法,首先确保数组里的已有的丑数是排好序的,同时要维护三个索引。代码:class Solution: def GetUglyNumber_Solution(self, index): if index<=0: return 0 res = [1] a, b, c = 0 while(len(res) < index): nextMin = min(res[a] * 2,res[b] * 3,res[c] * 5) res.append(nextMin) while res[a] * 2 <= nextMin: a += 1 while res[b] * 3 <= nextMin: b += 1 while res[c] * 5 <= nextMin: c += 1 return res[-1] 34.第一个只出现一次的字符在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写)。思路:创建哈希表,下标为ACII值,值为出现次数。代码class Solution: def FirstNotRepeatingChar(self, s): #建立哈希表,有256个字符,于是创建一个长度为256的列表 ls=[0]*256 #遍历字符串,下标为ASCII值,值为次数 for i in s: ls[ord(i)]+=1 #ord()函数以一个字符作为参数,返回对应的ASCII数值 for j in s: if ls[ord(j)]==1: return s.index(j) return -1 35.数组中的逆序对在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007#使用归并排序的思路求解 class Solution: def InversePairs(self, data): if len(data) > 1: mid = len(data) / 2 left_half = data[:mid] right_half = data[mid:] left_count = self.InversePairs(left_half)%1000000007 right_count = self.InversePairs(right_half)%1000000007 i,j,k,count = len(left_half)-1,len(right_half)-1,len(data)-1,0 while i >= 0 and j >= 0: if left_half[i] < right_half[j]: data[k] = right_half[j] j = j - 1 k = k - 1 else: data[k] = left_half[i] count += (j+1) i = i - 1 k = k - 1 while i >= 0: data[k] = left_half[i] k = k - 1 i = i - 1 while j>=0: data[k] = right_half[j] k = k - 1 j = j - 1 return (count + left_count + right_count)%1000000007 else: return 0 36.两个链表的第一个公共结点(leetcode160) 编写一个程序,找到两个单链表相交的起始节点。如下面的两个链表:在节点 c1 开始相交。注意:如果两个链表没有交点,返回 null.在返回结果后,两个链表仍须保持原有的结构。可假定整个链表结构中没有循环。程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。分析设置两个指针,一个从headA开始遍历,遍历完headA再遍历headB,另一个从headB开始遍历,遍历完headB再遍历headA,如果有交点,两个指针会同时遍历到交点处。代码class Solution(object): def getIntersectionNode(self, headA, headB): p1 = headA p2 = headB while p1 != p2: if p1 == None: p1 = headB else: p1 = p1.next if p2 == None: p2 = headA else: p2 = p2.next return p2 37.统计一个数字在排序数组中的出现的次数思路:考虑数组为空的情况,直接返回0;双指针,找到i和j的位置。class Solution: def GetNumberOfK(self, data, k): if len(data) == 0: return 0 i = 0 j = len(data) - 1 while i < j and data[i] != data[j]: if data[i] < k: i += 1 if data[j] > k: j -= 1 if data[i] != k: return 0 return j-i+1 38.二叉树深度 class Solution(object): def maxDepth(self, root): if root is None: return 0 else: return max(self.maxDepth(root.left),self.maxDepth(root.right))+1 39.判断是否是平衡二叉树 平衡二叉树:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。 class Solution(object): def isBalanced(self, root): if root == None: return True elif abs(self.height(root.left)-self.height(root.right))>1: return False else: return self.isBalanced(root.left) and self.isBalanced(root.right) def height(self,root): if root == None: return 0 else: return max(self.height(root.left),self.height(root.right))+ 1 41.和为S的连续正数序列输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序。思路:维护两个指针,一个指针指向这个连续正数序列的开始,一个指向连续正数序列的结束,判断当前的序列和与目标的关系,不断更新这两个指针的位置。代码:class Solution: def FindContinuousSequence(self, tsum): res = [] i = 1 j = 2 curSum = i + j while i <= tsum/2: if curSum == tsum: res.append(range(i,j+1)) j = j + 1 curSum += j elif curSum > tsum: curSum -= i i += 1 else: j += 1 curSum += j return res 42.和为S的两个数字输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。思路:由于是排好序的数组,因此对于和相等的两个数来说,相互之间的差别越大,那么乘积越小,因此我们使用两个指针,一个从前往后遍历,另一个从后往前遍历数组即可。代码:class Solution: def FindNumbersWithSum(self, array, tsum): if len(array)<2: return [] i = 0 j = len(array)-1 while i < j: if array[i]+array[j] > tsum: j -= 1 elif array[i]+array[j] < tsum: i += 1 else: return [array[i],array[j]] return [] 43.左旋转字符串对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。思路:分割法。class Solution: def LeftRotateString(self, s, n): m = len(s) res1 = s[n:m] res2 = s[0:n] res = res1+res2 return res 44.翻转单词顺序列例如,“student. a am I”翻转为“I am a student.”。思路:按空格切分为数组,依次入栈,再出栈(用空格连接)class Solution: def ReverseSentence(self, s): if s is None or len(s) == 0: return s stack = [] for i in s.split(' '): #split()通过指定分隔符对字符串进行切片 stack.append(i) res = "" while len(stack) > 0: res += stack.pop() + " " res = res[:-1] return res 49.把字符串转换成整数将一个字符串转换成一个整数(实现Integer.valueOf(string)的功能,但是string不符合数字要求时返回0),要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0。输入描述:输入一个字符串,包括数字字母符号,可以为空输出描述:如果是合法的数值表达则返回该数字,否则返回0示例1:输入:+2147483647 ,输出:2147483647;输入:1a33,输出:0。代码:class Solution: def StrToInt(self, str): str = str.strip() if not str: return 0 number, flag = 0, 1 #符号位的判断是否有正负号 if str[0] == '-': str = str[1:] flag = -1 elif str[0] == '+': str = str[1:] #遍历除+,-以外的所有字符,如果遇到非数字,则直接返回0 for c in str: if c >= '0' and c <= '9': number = 10*number + int(c) else: return 0 number = flag * number return number 55.链表中环的入口节点给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。思路:快慢指针,快指针一次走两步,慢指针一次走一步。如果链表中存在环,且环中假设有n个节点,那么当两个指针相遇时,快的指针刚好比慢的指针多走了环中节点的个数,即n步。从另一个角度想,快的指针比慢的指针多走了慢的指针走过的步数,也是n步。相遇后,快指针再从头开始走,快慢指针再次相遇时,所指位置就是入口。代码:# class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: def EntryNodeOfLoop(self, pHead): if pHead==None or pHead.next==None or pHead.next.next==None: return None low=pHead.next fast=pHead.next.next while low!=fast: if fast.next==None or fast.next.next==None: return None low=low.next fast=fast.next.next fast=pHead while low!=fast: low=low.next fast=fast.next return fast 56.删除链表中重复的结点 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5。(leetcode82) # Definition for singly-linked list. # class ListNode(object): # def __init__(self, x): # self.val = x # self.next = None class Solution(object): def deleteDuplicates(self, head): dummy = ListNode(-1) dummy.next = head pre = dummy cur = head while cur: while cur.next and cur.val == cur.next.val: cur = cur.next if pre.next == cur: pre = pre.next else: pre.next = cur.next cur = cur.next return dummy.next 58.对称的二叉树 请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。(leetcode101题) class Solution: def isSymmetrical(self, pRoot): if pRoot is None: return True return self.isSymmetricTree(pRoot.left,pRoot.right) def isSymmetricTree(self,left,right): if left is None and right is None: return True if left is None or right is None or left.val != right.val: return False return self.isSymmetricTree(left.left,right.right) and self.isSymmetricTree(left.right,right.left) 59.把二叉树打印成多行从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。(leetcode102题)给定二叉树: [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 class Solution: def Print(self, pRoot): queue = [pRoot] res = [] if not pRoot: return [] while queue: templist = [] templen = len(queue) for i in range(templen): temp = queue.pop(0) templist.append(temp.val) if temp.left: queue.append(temp.left) if temp.right: queue.append(temp.right) res.append(templist) return res 作者:半情调 链接:https://zhuanlan.zhihu.com/p/74641093 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 61.二叉搜索树的第K个节点给定一棵二叉搜索树,请找出其中的第k小的结点。例如,(5,3,7,2,4,6,8)中,按结点数值大小顺序第三小结点的值为4。思路:如果是按中序遍历二叉搜索树的话,遍历的结果是递增排序的。所以只需要中序遍历就很容易找到第K个节点。class Solution: def __init__(self): self.my_list = [] # 用于保存中序遍历的序列的结点 def in_order(self, pRoot): # 中序遍历二叉树,并把结果保存到my_list中 if not pRoot: return None if pRoot.left: self.in_order(pRoot.left) self.my_list.append(pRoot) if pRoot.right: self.in_order(pRoot.right) def KthNode(self, pRoot, k): self.in_order(pRoot) if k <= 0 or k > len(self.my_list): # 越界 return None return self.my_list[k - 1] 65.机器人的运动范围地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?思路:还是利用递归对矩阵进行深度优先搜索,从(0,0)位置出发,每成功走一步标记当前位置为true,然后从当前位置往四个方向探索,返回1 + 4 个方向的探索值之和。判断当前节点是否可达的标准为:当前节点在矩阵内;当前节点未被访问过;当前节点满足K的限制。class Solution: def __init__(self): # 机器人可以倒回来,但不能重复计数。 self.count = 0 def movingCount(self, threshold, rows, cols): flag = [[1 for i in range(cols)] for j in range(rows)] self.findWay(flag,0,0,threshold) # 从(0,0)开始走 return self.count def findWay(self,flag,i,j,k): if i >= 0 and j >= 0 and i < len(flag) and j < len(flag[0]) and sum(list(map(int,str(i)))) + sum(list(map(int,str(j)))) <= k and flag[i][j] == 1: flag[i][j] = 0 self.count += 1 self.findWay(flag,i-1,j,k) self.findWay(flag,i+1,j,k) self.findWay(flag,i,j-1,k) self.findWay(flag,i,j+1,k) 1.二维数组中的查找 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。 class Solution: def Find(self, target, array): rows = len(array)-1 cols = len(array[0]) - 1 i = rows j = 0 while j<=cols and i>=0: if target<array[i][j]: i -= 1 elif target>array[i][j]: j += 1 else: return True return False 4.重建二叉树输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。思路:先序遍历和中序遍历的关系,先序遍历的第一个值是根节点的值。在中序遍历中,根节点左边的值是左子树,右边的值是右子树上的值。代码class Solution: # 返回构造的TreeNode根节点 def reConstructBinaryTree(self, pre, tin): if not pre: return None root = TreeNode(pre[0]) n = tin.index(root.val) #找到根节点在中序遍历中的下标 root.left = self.reConstructBinaryTree(pre[1:n+1],tin[:n]) root.right = self.reConstructBinaryTree(pre[n+1:],tin[n+1:]) return root 5.用两个栈实现一个队列用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。思路定义两个stack,分别是stack1和stack2,队列的push和pop是在两侧的,push操作很简单,只需要在stack1上操作,而pop操作时,先将stack1的所有元素push到stack2中,然后stack2的pop返回的元素即为目标元素,然后把stack2中的所有元素再push到stack1中。代码class Solution: def __init__(self): self.stack1 = [] self.stack2 = [] def push(self, node): self.stack1.append(node) def pop(self): if not self.stack1: return None while self.stack1: self.stack2.append(self.stack1.pop()) res = self.stack2.pop() while self.stack2: self.stack1.append(self.stack2.pop()) return res 作者:半情调 链接:https://zhuanlan.zhihu.com/p/75864673 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 6.旋转数组中的最小数字把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。思路:这个题很简单,题目说的不明白,意思是一个递增排序的数组做了一次旋转,给你旋转后的数组,找到最小元素。输入{3,4,5,1,2}输出1。两个方法:1.遍历数组元素,如果前一个元素大于后一个元素,则找到了最小的元素。如果前一个一直小于后一个元素,说明没有旋转,返回第一个元素。2.二分查找,如果中间元素位于递增元素,那么中间元素>最右边元素,最小元素在后半部分。否则,最小元素在前半部分。代码1.时间复杂度O(n)class Solution: def minNumberInRotateArray(self, rotateArray): if not rotateArray: return 0 for i in range(len(rotateArray)-1): if rotateArray[i] > rotateArray[i+1]: return rotateArray[i+1] return rotateArray[0]2.二分查找时间复杂度O(logn)class Solution: def minNumberInRotateArray(self, rotateArray): if not rotateArray: return 0 l = 0 r = len(rotateArray) - 1 while l < r: mid = (l + r)/2 if rotateArray[mid] > rotateArray[r]: l = mid+1 else: r = mid return rotateArray[l] 8.跳台阶一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。思路:典型的动态规划问题,对于第n阶台阶来说,有两种办法,一种是爬一个台阶,到第n-1阶;第二种是爬两个台阶,到第n-2阶。得出动态规划递推式: F(n)=F(n−1)+F(n−2)F(n)=F(n-1)+F(n-2)F(n)=F(n-1)+F(n-2)代码class Solution: def jumpFloor(self, number): if number < 0: return 0 if number == 1: return 1 if number == 2: return 2 result = [1, 2] for i in range(2,number): result.append(result[i-1] + result[i-2]) return result[-1] 14.链表中的倒数第K个节点输入一个链表,输出该链表中倒数第k个结点。思路:假设链表中的节点数大于等于k个,那么一定会存在倒数第k个节点,首先使用一个快指针先往前走k步,然后两个指针每次走一步,两个指针之间始终有k的距离,当快指针走到末尾时,慢指针所在的位置就是倒数第k个节点。代码class Solution: def FindKthToTail(self, head, k): if not head or k <=0: return None p = q = head t = 0 while p and t < k: p = p.next t = t+1 if t < k: return None while p != None: p = p.next q = q.next return q 15.反转链表class Solution(object): def reverseList(self, head): if not head: return None p = head q = head.next while q: head.next = q.next q.next = p p = q q = head.next return p 16.合并两个排序的链表输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。class Solution(object): def mergeTwoLists(self, l1, l2): cur = head =ListNode(0) while l1 and l2: if l1.val <= l2.val: cur.next = l1 l1 = l1.next else: cur.next = l2 l2 = l2.next cur = cur.next cur.next = l1 or l2 return head.next 18.二叉树的镜像操作给定的二叉树,将其变换为源二叉树的镜像。二叉树的镜像定义:源二叉树 8 / \ 6 10 / \ / \ 5 7 9 11 镜像二叉树 8 / \ 10 6 / \ / \ 11 9 7 5代码:交换左右结点class Solution(object): def invertTree(self, root): if not root: return None root.left,root.right = self.invertTree(root.right),self.invertTree(root.left) return root 24.二叉树中和为某一值的路径输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)思路:定义一个子函数,输入的是当前的根节点、当前的路径以及还需要满足的数值,同时在子函数中运用回溯的方法进行判断。代码class Solution: # 返回二维列表,内部每个列表表示找到的路径 def FindPath(self, root, expectNumber): self.res = [] if not root: return [] self.subPath(root,[],expectNumber) return self.res def subPath(self, root, path,number): if not root.left and not root.right: if number == root.val: self.res.append(path+[root.val]) if root.left: self.subPath(root.left,path+[root.val],number-root.val) if root.right: self.subPath(root.right,path+[root.val],number-root.val) 27.字符串的排列输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。思路:递归。把字符串分为两个部分: 字符串的第一个字符,第一个字符后面的所有字符。1.求所有可能出现在第一个位置的字符,用索引遍历。2.求第一个字符以后的所有字符的全排列。将后面的字符又分成第一个字符以及剩余字符。class Solution: def Permutation(self, ss): if len(ss)==0 or len(ss)==1: return ss res = [] self.helper(ss, res, '') return sorted(list(set(res))) def helper(self, ss, res, path): if not ss: res.append(path) else: for i in range(len(ss)): self.helper(ss[:i]+ss[i+1:],res,path+ss[i]) 30.连续子数组的最大和 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。 思路:如果数组里所有的整数都是负数,那么选择最大的数即可,因为越累加越小。 正负数都有的情况,需要两个变量,一个是global_max,从全局来看,每次最大的是什么组合,另一个是local_max,和global_max相比,更新global_max。 代码 class Solution(object): def maxSubArray(self, nums): if max(nums) < 0: return max(nums) local_max, global_max = 0, 0 for i in nums: local_max = max(0, local_max + i) global_max = max(global_max, local_max) return global_max