********************************************* 2018-05-22 May Tuesday the 21 week, the 142 day SZ 这个文档用python在Leetcode上来刷题,打算每天早上过来后先刷3道题,周末刷10道题。一个月140个题。 这个是中文版的 标注’问题‘的说明还有些问题,方便以后搜索查询 网页版使用说明:在问题前面画上对号的说明自己已经提交成功了 刚开始刷题很慢,每天只能刷3道题左右,因为很多题目网友的答案没有解说,自己只能用print去输出结果,去猜测网友的脑洞,最后才发现网友真的是太有才了。 后来多看几个网友的答案,自己再想想自己的答案,然后一道题就能够耗费一个上午。 ********************************************* ######################## 算法 容易 数组部分, 汉化版 leetcode,PYTHON题答案 ###################### 1 去除数组中重复数字,并且返回新数组 从排序数组中删除重复项 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。 示例 1: 给定数组 nums = [1,1,2], 函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。 你不需要考虑数组中超出新长度后面的元素。 示例 2: 给定 nums = [0,0,1,1,1,2,2,3,3,4], 函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。 你不需要考虑数组中超出新长度后面的元素。 #这段代码耗时非常短,主要是假设了列表是排好序的。当然也可以用函数先对无序列表排序 class Solution(object): def removeDuplication(self,old_list): i = 0 while i < len(old_list)-1: if old_list[i] == old_list[i+1]: old_list.remove(old_list[i]) else: i += 1 return old_list my_solution = Solution() old_list = [1,1,2,2,3] a = my_solution.removeDuplication(old_list) print(a) [1, 2, 3] [Finished in 0.5s] 方法2 class Solution(object): def removeDuplication(self,old_list): new_list = list(set(old_list)) #set函数可以去除列表中的重复元素,并且变成集合的形式,所以前面添加的list又把集合转化为列表形式输出 return new_list my_solution = Solution() old_list = [1,1,2,2,3] a = my_solution.removeDuplication(old_list) print(a) [1, 2, 3] [Finished in 5.6s] 2 买卖股票的最佳时机 II 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 示例 1: 输入: [7,1,5,3,6,4] 输出: 7 解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。 随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。 示例 2: 输入: [1,2,3,4,5] 输出: 4 解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。 注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。 因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。 示例 3: 输入: [7,6,4,3,1] 输出: 0 解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。 #交易多次股票求最大利润的代码 class Solution(object): def maxProfit(prices): """ :type prices: List[int] :rtype: int """ if prices is None or len(prices) ==0: return 0 begin_value = prices[0] result = 0 for i in prices: if i > begin_value: result= result + i - begin_value #多次买入求累计利润 begin_value = i #重新买入 else: begin_value = min(i, begin_value) return result prices = [7,1,5,3,6,4] a = Solution.maxProfit(prices) print(a) 3 通过 2018-05-23 May Wednesday the 21 week, the 143 day SZ 旋转数组 给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。 示例 1: 输入: [1,2,3,4,5,6,7] 和 k = 3 输出: [5,6,7,1,2,3,4] 解释: 向右旋转 1 步: [7,1,2,3,4,5,6] 向右旋转 2 步: [6,7,1,2,3,4,5] 向右旋转 3 步: [5,6,7,1,2,3,4] 示例 2: 输入: [-1,-100,3,99] 和 k = 2 输出: [3,99,-1,-100] 解释: 向右旋转 1 步: [99,-1,-100,3] 向右旋转 2 步: [3,99,-1,-100] 说明: •尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。 •要求使用空间复杂度为 O(1) 的原地算法 #python 给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。 class Solution(object): def rotate(self, nums, k): """ :type nums: List[int] :type k: int :rtype: void Do not return anything, modify nums in-place instead. """ len_nums = len(nums) nums[:] = nums[len_nums-k:] + nums[:len_nums-k] test_nums1 = [-1, -100, 3, 99] test_nums2 = [1, 2, 3, 4, 5, 6, 7] my_solution = Solution() my_solution.rotate(test_nums1, 2) my_solution.rotate(test_nums2, 3) print(test_nums1) print(test_nums2) 4 通过 2018-05-23 May Wednesday the 21 week, the 143 day SZ 存在重复 给定一个整数数组,判断是否存在重复元素。 如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。 示例 1: 输入: [1,2,3,1] 输出: true 示例 2: 输入: [1,2,3,4] 输出: false 示例 3: 输入: [1,1,1,3,3,4,3,2,4,2] 输出: true ''' 思路: 通过set函数删除重复数字,然后通过判断新旧数组长度是否相同 ''' class Solution(object): def containsDuplicate(self, nums): """ :type nums: List[int] :rtype: bool """ if len(set(nums)) == len(nums): #set函数删除重复数字,并且把数组变成集合形式 return False else: return True test_nums2 = [1, 2, 3, 3, 5, 6, 7] my_solution = Solution() a = my_solution.containsDuplicate(test_nums2) print(a) 5 通过 只出现一次的数字 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 说明: 你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗? 示例 1: 输入: [2,2,1] 输出: 1 示例 2: 输入: [4,1,2,1,2] 输出: 4 方法1:异或法 #^异或代表,两个数不同时候为1. class Solution(object): def singleNumber(self, nums): temp = 0 for i in nums: temp = temp ^ i #任何数和0异或都是本身,两个相同的数字异或为0 return temp my_solution = Solution() nums = [4,1,2,1,2] a = my_solution.singleNumber(nums) print(a) 6 两个数组的交集 问题 给定两个数组,写一个方法来计算它们的交集。 例如: 给定 nums1 = [1, 2, 2, 1], nums2 = [2, 2], 返回 [2, 2]. 注意: • 输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。 • 我们可以不考虑输出结果的顺序。 跟进: •如果给定的数组已经排好序呢?你将如何优化你的算法? •如果 nums1 的大小比 nums2 小很多,哪种方法更优? •如果nums2的元素存储在磁盘上,内存是有限的,你不能一次加载所有的元素到内存中,你该怎么办? ''' 解法1 思路:暴力法,循环比较数组2中是否有某个值和数组1中相同 ''' class Solution(object): def intersect(self, nums1, nums2): """ :type nums1: List[int] :type nums2: List[int] :rtype: List[int] """ res = [] for num1 in nums1: #index = -1 for j in range(0, len(nums2)): if nums2[j] == num1: index = j break if index != -1: res.append(num1) del nums2[index] return res my_solution = Solution() nums1 = [1,2,2] nums2 = [3,2,2,1] a = my_solution.intersect(nums1, nums2) print(a) ''' 解法2通过 思路:先给数组排序,然后用两个指针依次比较,如果相等则指针都加一,如果.... ''' class Solution(object): def intersect(self, nums1, nums2): """ :type nums1: List[int] :type nums2: List[int] :rtype: List[int] """ res = [] nums1.sort() nums2.sort() i = j = 0 while i < len(nums1) and j < len(nums2): if nums1[i] == nums2[j]: res.append(nums1[i]) i+=1 j+=1 elif nums1[i] < nums2[j]: i += 1 else: j +=1 return res my_solution = Solution() nums1 = [1,2,2] nums2 = [3,2,4,1] a = my_solution.intersect(nums1, nums2) print(a) ''' for i in range(len(nums1)): for j in range(len(nums2)): ''' 7 加一 给定一个非负整数组成的非空数组,在该数的基础上加一,返回一个新的数组。 最高位数字存放在数组的首位, 数组中每个元素只存储一个数字。 你可以假设除了整数 0 之外,这个整数不会以零开头。 示例 1: 输入: [1,2,3] 输出: [1,2,4] 解释: 输入数组表示数字 123。 示例 2: 输入: [4,3,2,1] 输出: [4,3,2,2] 解释: 输入数组表示数字 4321。 #2018-05-30 May Wednesday the 22 week, the 150 day SZ ''' 解法1 思路: 把列表看成整数,然后加一,输出。第一步:把列表转化为整数,第二部整数加一然后转化为列表输出 把列表看成十进制数字,个位乘以1,十位乘以10,以此类推。 把列表反转,然后进行十进制转化,enumerate函数把列表组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。 返回的那个数字加一就行了,然后把返回的数字列表化。map() 会根据提供的函数对指定序列做映射。 ''' class Solution: def plusOne(self, digits): dint = 0 for i,j in enumerate(digits[::-1]): #digits[::-1]可以把列表里面元素反转,digits只是按照原样输出 dint += j*10**i #print(i,j,dint) return list(map(int,str(dint+1))) #map()函数Python 2.x 返回列表。Python 3.x 返回迭代器。int() 函数用于将一个字符串或数字转换为整型。str()函数返回一个对象的string格式。 my_solution = Solution() nums = [4,1,2,3] print(list(enumerate(nums[::-1]))) a = my_solution.plusOne(nums) print(a) [4, 1, 2, 4] [Finished in 0.5s] 在LeetCode里面算是最慢的算法了。但就是简洁,简单到让人尖叫 #2018-05-30 May Wednesday the 22 week, the 150 day SZ ''' 解法2思路: 利用递归法,用if判断末尾是否数字9,如果是,那就给删除9的数组继续递归,比上一个算法快些 ''' class Solution: def plusOne(self, digits): if len(digits) == 0: #判断数组长度,为空,返回1 digits = [1] elif digits[-1] == 9: #末尾为9 digits = self.plusOne(digits[:-1]) #递归调用函数,如果倒数第二位也是9,那就继续递归 digits.extend([0]) #数组末尾添加0 else: #如果末尾不是9,末尾加一 digits[-1] += 1 return digits my_solution = Solution() nums = [4,1,2,3] a = my_solution.plusOne(nums) print(a) 8 移动0 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 示例: 输入: [0,1,0,3,12] 输出: [1,3,12,0,0] 说明: 1.必须在原数组上操作,不能拷贝额外的数组。 2.尽量减少操作次数。 ''' 解法1没通过哈,思路: for循环把数字0和其他东西分开放在另外两个数组里面,然后把新建的两个数组相加。 leetcode给的错误信息,看了下,原来是人家要求只用一个数组解决问题。我总共使用了三个数组解决问题。 Line 63: SyntaxError: EOF while scanning triple-quoted string literal ''' class Solution: def moveZeroes(self, digits): digits1 = [] digits2 = [] for i in digits: if i ==0: digits1.extend([0]) else: digits2.extend([i]) return digits2 + digits1 my_solution = Solution() nums = [0,1,0,3,12] a = my_solution.moveZeroes(nums) print(a) [1, 3, 12, 0, 0] [Finished in 0.6s] #2018-05-30 May Wednesday the 22 week, the 150 day SZ ''' 解法2没通过哈,思路: for循环,碰到0,删除,最后添加一个0.循环一遍就搞定了 leetcode反馈如下,反正不让我通过 Do not return anything, modify nums in-place instead. ''' class Solution: def moveZeroes(self, digits): if len(digits) == 0: return digits else: for i in digits: if i ==0: digits.remove(i) digits.append(0) return digits my_solution = Solution() nums = [0,1,0,3,12] a = my_solution.moveZeroes(nums) print(a) [1, 3, 12, 0, 0] [Finished in 5.2s] leetcode反馈如下,反正不让我通过 Do not return anything, modify nums in-place instead. 我目前还没有发现问题在哪里 #2018-05-30 May Wednesday the 22 week, the 150 day SZ ''' 解法3通过哈,思路: #if保证找到非零元素,如果是0,就不会执行if 下面的语句。index确定零元素的起始位置。 ''' class Solution(object): def moveZeroes(self, nums): """ :type nums: List[int] :rtype: void Do not return anything, modify nums in-place instead. """ index = 0 for n in nums: if n: #保证找到非零元素,如果是0,就不会执行if 下面的语句 nums[index] = n index += 1 for i in range(index, len(nums)): nums[i] = 0 #return nums #题目要求不要返回值,所以这行删除,所有行为都是在原数组上操作。 my_solution = Solution() nums = [0,1,0,3,12] a = my_solution.moveZeroes(nums) print(a) 2018-05-23 May Wednesday the 21 week, the 143 day SZ 9 两数之和 给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。 示例: 给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1] ''' 解法1通过,思路: for循环做两个纸针,第一个指针保持不动,一次增大第二个指针。然后再增大第一个指针。这样保证所有数字都充分利用了 ''' class Solution(object): def twoSum(self, nums, target): """ :type nums: List[int] :type target: int :rtype: List[int] """ len_nums = len(nums) for i in range(len_nums): for j in range(i +1, len_nums): if nums[i] == target - nums[j]: return i, j break #break保证i只能被使用一次。要不然同一个i会有几个j对应。 else: continue my_solution = Solution() nums = [0,1,0,3,12] a = my_solution.twoSum(nums,15) print(a) ''' 解法2没有通过,思路: 用一个for循环查找target - nums[i]是否存在nums列表中 ''' class Solution(object): def twoSum(self, nums, target): """ :type nums: List[int] :type target: int :rtype: List[int] """ len_nums = len(nums) for i in range(len_nums): a = target - nums[i] if a in nums: j = nums.index(a) #index函数求匹配元素的第一个索引,如果列表有重复元素就完蛋了 return i,j break #break保证i只能被使用一次。要不然同一个i会有几个j对应。 else: continue my_solution = Solution() nums = [0,1,0,3,12] a = my_solution.twoSum(nums,15) print(a) 10 有效的数独 判断一个 9x9 的数独是否有效。只需要根据以下规则,验证已经填入的数字是否有效即可。 1.数字 1-9 在每一行只能出现一次。 2.数字 1-9 在每一列只能出现一次。 3.数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。 上图是一个部分填充的有效的数独。 数独部分空格内已填入了数字,空白格用 '.' 表示。 示例 1: 输入: [ ["5","3",".",".","7",".",".",".","."], ["6",".",".","1","9","5",".",".","."], [".","9","8",".",".",".",".","6","."], ["8",".",".",".","6",".",".",".","3"], ["4",".",".","8",".","3",".",".","1"], ["7",".",".",".","2",".",".",".","6"], [".","6",".",".",".",".","2","8","."], [".",".",".","4","1","9",".",".","5"], [".",".",".",".","8",".",".","7","9"] ] 输出: true 示例 2: 输入: [ ["8","3",".",".","7",".",".",".","."], ["6",".",".","1","9","5",".",".","."], [".","9","8",".",".",".",".","6","."], ["8",".",".",".","6",".",".",".","3"], ["4",".",".","8",".","3",".",".","1"], ["7",".",".",".","2",".",".",".","6"], [".","6",".",".",".",".","2","8","."], [".",".",".","4","1","9",".",".","5"], [".",".",".",".","8",".",".","7","9"] ] 输出: false 解释: 除了第一行的第一个数字从 5 改为 8 以外,空格内其他数字均与 示例1 相同。 但由于位于左上角的 3x3 宫内有两个 8 存在, 因此这个数独是无效的。 说明: •一个有效的数独(部分已被填充)不一定是可解的。 •只需要根据以上规则,验证已经填入的数字是否有效即可。 •给定数独序列只包含数字 1-9 和字符 '.' 。 •给定数独永远是 9x9 形式的。 ''' 数独成立条件: 一个9行9列的棋盘,每行每列和每一个3*3的小方格都不能有重复的数字,并且数字只能是0-9,逐一判断这些规则是否满足即可 解法1,思路: 依照规则,依次次判断每行元素是否重复,每列元素是否重复,每个小的九宫格是否重复。 判断数列是否有重复数字的方法就是给同一个数字赋相同的值,如果成立,就说明碰到重复的数字了 用数组里面的值给对应的空列表赋值,同样的数字只能给对应的地方赋值,如果发现坑已经被占了,那肯定有人来过。这个想法不错 ''' class Solution: # @param {character[][]} board # @return {boolean} def isValidSudoku(self, board): if len(board)!=9 or len(board[0])!=9:return False #确认是个9行9列的数组 for i in range(9): #0到8总共9次循环,确定行没有重复数字 map=[0 for k in range(10)] #得到一个有十个0的列表[0, 0, 0, 0, 0, 0, 0, 0, 0, 0] for j in range(9): if board[i][j]=='.':continue #放过空格 if board[i][j]<'0' or board[i][j]>'9':return False #数字在0到9之外就不是数独了 num = ord(board[i][j])-ord('0') #得到board[i][j]的数值,ord函数可以得到对应字符的数字形式 if map[num]==1:return False #print("map[num] is:",map[num]) map[num]=1 #print("map[num] is:",map[num]) #0到8总共9次循环,确定列没有重复数字 for j in range(9): map=[0 for k in range(10)] for i in range(9): if board[i][j]=='.':continue num = ord(board[i][j])-ord('0') #print("num is:",num) if map[num]==1:return False #判断是否有重复的数字:第一次map[num]被赋值1,如果再次碰到同一个num,map[num]等于1成立,然后返回False,程序退出循环 #print("map[num] is:",map[num]) map[num]=1 #print("map[num] is:",map[num]) #确定小宫格的情况 for i in range(0,9,3): for j in range(0,9,3): map=[0 for k in range(10)] for k in range(i,i+3): for l in range(j,j+3): if board[k][l]=='.':continue num = ord(board[k][l])-ord('0') if map[num]==1:return False map[num]=1 return True my_solution = Solution() board1 = [ ["8","3",".",".","7",".",".",".","."], ["6",".",".","1","9","5",".",".","."], [".","9","8",".",".",".",".","6","."], ["8",".",".",".","6",".",".",".","3"], ["4",".",".","8",".","3",".",".","1"], ["7",".",".",".","2",".",".",".","6"], [".","6",".",".",".",".","2","8","."], [".",".",".","4","1","9",".",".","5"], [".",".",".",".","8",".",".","7","9"] ] board2 = [ ["5","3",".",".","7",".",".",".","."], ["6",".",".","1","9","5",".",".","."], [".","9","8",".",".",".",".","6","."], ["8",".",".",".","6",".",".",".","3"], ["4",".",".","8",".","3",".",".","1"], ["7",".",".",".","2",".",".",".","6"], [".","6",".",".",".",".","2","8","."], [".",".",".","4","1","9",".",".","5"], [".",".",".",".","8",".",".","7","9"] ] a = my_solution.isValidSudoku(board1) print(a) b = my_solution.isValidSudoku(board2) print(b) 2018-05-23 May Wednesday the 21 week, the 143 day SZ 11 旋转图像 给定一个 n × n 的二维矩阵表示一个图像。 将图像顺时针旋转 90 度。 说明: 你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。 示例 1: 给定 matrix = [ [1,2,3], [4,5,6], [7,8,9] ], 原地旋转输入矩阵,使其变为: [ [7,4,1], [8,5,2], [9,6,3] ] 示例 2: 给定 matrix = [ [ 5, 1, 9,11], [ 2, 4, 8,10], [13, 3, 6, 7], [15,14,12,16] ], 原地旋转输入矩阵,使其变为: [ [15,13, 2, 5], [14, 3, 4, 1], [12, 6, 8, 9], [16, 7,10,11] ] ''' 方法1直接旋转,太抽象,普通人想不到这里,真的很巧妙。 ''' class Solution(object): def rotate(self, matrix): """ :type matrix: List[List[int]] :rtype: void Do not return anything, modify matrix in-place instead. """ res = [] while matrix[0]: tmp = [] #print("matrix is:",matrix) for循环进行依次,就弹出旧数组的一列,并且放到新数组中组成一行 for row in matrix: #print("row is:",row) tmp.insert(0,row.pop(0)) #list.insert(position,value)。tmp里面放的是新图片的行 #print("tmp is:",tmp) #print("temp is",tmp) res.append(tmp) #把所有的tmp行放到res中,res就是翻转后的新图像 #print("res is:",res) #把res赋给旧图片 for i in range(len(matrix)): #这里,必须对matrix中的每行都进行修改,才能对其重新赋值,不能直接:matrix=res matrix[i] = res[i] print("for :",matrix[i]) s = Solution() matrix = [[1,2],[3,4]] s.rotate(matrix) print(matrix) ''' 方法2通过 思路: 先把矩阵按照对角线对换位置,然后新的矩阵按照行逆转,经过两步就是图片的九十度顺时针旋转了。 发散思维:如果图像逆时针旋转怎么办。 也是两步走,按照相反的对角线调换位置,然后把每行逆转就成功了 ''' class Solution(object): def rotate(self, matrix): """ :type matrix: List[List[int]] :rtype: void Do not return anything, modify matrix in-place instead. """ size = len(matrix) for i in range(size): for j in range(i + 1,size): matrix[i][j],matrix[j][i] = matrix[j][i],matrix[i][j] for i in range(size): matrix[i].reverse() s = Solution() matrix = [[1,2],[3,4]] s.rotate(matrix) print(matrix) *********************数组简单部分结束**************************************
LeetCode 数组 容易 python
猜你喜欢
转载自blog.csdn.net/btujack/article/details/80540401
今日推荐
周排行