├── C++ ├── 剑指 Offer 42. 连续子数组的最大和 └── 排序 │ └── 1528. 重新排列字符串 ├── Java └── 1528. 重新排列字符串 ├── 动态规划 └── 300. 最长上升子序列 ├── 基础知识 └── 461. 汉明距离 ├── 字符串 └── 13.罗马数字转整数 ├── 数组 ├── 11.盛最多水的容器 ├── 118.杨辉三角 ├── 119.杨辉三角2 ├── 121.买股票的最佳时机(配合最大子序和看) ├── 122.买卖股票的最佳时机 II ├── 1266.访问所有的的最小时间 ├── 136.只出现一次的数字 ├── 167.两数之和 II - 输入有序数组 ├── 169.多数元素 ├── 189.旋转数组 ├── 217.存在重复元素 ├── 219.存在重复元素2 ├── 268.缺失的数字 ├── 414.第三大的数 ├── 448.找到所有数组中消失的数字 ├── 485.最大连续1的个数 ├── 509.斐波那契数 ├── 532. 数组中的K-diff数对 ├── 561.数组拆分 ├── 566.重塑矩阵 ├── 605.种花问题 ├── 628.三个数的最大乘积 ├── 643.子数组最大平均数1 ├── 661.图片平滑器 ├── 665.非递减数列 ├── 667.优美的排列2 ├── 674.最长连续递增序列 ├── 两数之和 ├── 删除排序数组中的重复项 ├── 合并两个有序数组 ├── 搜索插入位置 ├── 数组加一 ├── 最大子序和 ├── 移动零到末尾 └── 移除指定元素 ├── 树 └── 617. 合并二叉树 └── 链表 └── 206. 反转链表 /C++/剑指 Offer 42. 连续子数组的最大和: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int maxSubArray(vector& nums) { 4 | assert(!nums.empty()); 5 | 6 | int n = nums.size(); 7 | int maxSum = nums[0]; 8 | 9 | // 将i-1看作当前值,如果当前值小于0, 10 | // 重新开始(全局最大值更新) 11 | for (int i = 1; i < n; i++) { 12 | // 更新当前的最大值 13 | if (nums[i - 1] > 0) { 14 | nums[i] += nums[i - 1]; 15 | } 16 | // 更新全局的最大值 17 | maxSum = std::max(nums[i], maxSum); 18 | } 19 | 20 | return maxSum; 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /C++/排序/1528. 重新排列字符串: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | string restoreString(string s, vector& indices) { 4 | int len1=s.size(); 5 | int len2=indices.size(); 6 | if(len1!=len2) 7 | return ""; 8 | //一个有趣的声明字符串的方式 9 | string ret(len1,'0'); 10 | for(int i=0;i nums[j]: 23 | #因为dp中每一个位置的元素代表了nums中对应位置元素结尾的序列长度 24 | #设想一种情况 25 | #nums中在一直递增过程中出现一个数值很小的元素,后面还有大数,以这个元素结尾的序列很短 26 | #需要忽视掉,于是就用max,遇到小元素就忽视掉,拿着之前的大元素结尾的序列长度 27 | dp[i] = max(dp[i], dp[j] + 1) 28 | dp[i] = dp[j]+1 29 | return max(dp) 30 | -------------------------------------------------------------------------------- /基础知识/461. 汉明距离: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def hammingDistance(self, x, y): 3 | """ 4 | :type x: int 5 | :type y: int 6 | :rtype: int 7 | """ 8 | #^计算异或,即不同置1,再统计异或的数量 9 | return bin(x^y).count('1') 10 | -------------------------------------------------------------------------------- /字符串/13.罗马数字转整数: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def romanToInt(self, s): 3 | """ 4 | :type s: str 5 | :rtype: int 6 | """ 7 | #很简单的道理,前面的值比后面小就减,比后面的大就加,在最后一个前停下 8 | a = 0 9 | t = 0 10 | dic = {'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M':1000} 11 | for i in range(len(s)-1): 12 | if dic[s[i]] < dic[s[i+1]]: 13 | t = -dic[s[i]] 14 | else: 15 | t = dic[s[i]] 16 | a += t 17 | #最后一个一定是加 18 | a += dic[s[len(s)-1]] 19 | return a 20 | 21 | -------------------------------------------------------------------------------- /数组/11.盛最多水的容器: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def maxArea(self, height): 3 | """ 4 | :type height: List[int] 5 | :rtype: int 6 | """ 7 | #用逆向双指针法 8 | j = len(height) - 1 9 | i = 0 10 | #记录最大值 11 | maxcover = 0 12 | while True: 13 | #最大值和当前值作比较选出新的最大值 14 | maxcover = max(maxcover,(min(height[j],height[i]))*(j-i)) 15 | #相遇了就退出 16 | if i == j: 17 | break 18 | #低的那一方向中间移动, 19 | #因为能盛多少水是低的说了算,如果移动高的,只会缩短水平距离,容积只会变小 20 | #如果移动低的,虽然距离变小,但最低高度可能变大,容积是有可能变大的 21 | #只要用maxcover记录历史最大,再和每次变化的容积比较就好 22 | if height[i] < height[j]: 23 | i += 1 24 | else: 25 | j -= 1 26 | return maxcover 27 | -------------------------------------------------------------------------------- /数组/118.杨辉三角: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def generate(self, numRows): 3 | """ 4 | :type numRows: int 5 | :rtype: List[List[int]] 6 | """ 7 | '''mymethod 8 | #把它看成直角三角形,贴着左边 9 | #先拿出特殊情况 10 | if numRows == 0: 11 | return[] 12 | if numRows == 1: 13 | return [[1],] 14 | else: 15 | #第0行先写好, 16 | a = [[1],] 17 | #从1行开始,这样才能用上一行的数 18 | for i in range(1,numRows): 19 | b = [] 20 | for j in range(i+1): 21 | #如果左上角没数 22 | if j == 0: 23 | x = 0 24 | else: 25 | x = a[i-1][j-1] 26 | #如果右上角没数 27 | if j == i: 28 | y = 0 29 | else: 30 | print(j) 31 | y = a[i-1][j] 32 | b.append(x+y) 33 | a.append(b) 34 | return a 35 | #这是一个二维数组,不可能通过一次循环实现,所以解析也只是代码更简单而已,时间复杂度一样 36 | ''' 37 | triangle = [] 38 | for row_num in range(numRows): 39 | # 最左和最右都是1 40 | #先把数组整出来 41 | row = [None for _ in range(row_num+1)] 42 | #左右置1 43 | row[0], row[-1] = 1, 1 44 | # Each triangle element is equal to the sum of the elements 45 | # above-and-to-the-left and above-and-to-the-right. 46 | for j in range(1, len(row)-1): 47 | row[j] = triangle[row_num-1][j-1] + triangle[row_num-1][j] 48 | 49 | triangle.append(row) 50 | 51 | return triangle 52 | -------------------------------------------------------------------------------- /数组/119.杨辉三角2: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def getRow(self, rowIndex): 3 | """ 4 | :type rowIndex: int 5 | :rtype: List[int] 6 | """ 7 | if rowIndex == 0: 8 | return [1] 9 | a = [[1],] 10 | b = [] 11 | x, y = 0,0 12 | 13 | for i in range(1,rowIndex+1): 14 | b = [] 15 | for j in range(i+1): 16 | if j == 0: 17 | x = 0 18 | else: 19 | x = a[i-1][j-1] 20 | if j == i: 21 | y = 0 22 | else: 23 | y = a[i-1][j] 24 | b.append(x+y) 25 | a.append(b) 26 | return b 27 | -------------------------------------------------------------------------------- /数组/121.买股票的最佳时机(配合最大子序和看): -------------------------------------------------------------------------------- 1 | def maxProfit(self, prices): 2 | #第i天的总收益 3 | last = 0 4 | #当前情况下之前曾出现过的最高收益 5 | profit = 0 6 | for i in range(1,len(prices)): 7 | #第i天的价格可能会比第i-1天价格低,但是只要比买入时高,即总收益last>0 8 | #我依然让你保留下来,当作我新的总收益,谁知道你的下一天会涨破天际呢? 9 | #那我拿一个比你现在更小的数等个你明天的大数岂不赚翻?而你这次的利润不是我曾经最高的 10 | #我的下一步会用profit把你比掉 11 | #但是如果因为你的存在,让我亏本了,last<=0了,那么从买入到现在的这段时间就没有存在的必要了 12 | #你会成为我新的买入起点,再用你之后的利益和我曾经的最大利益profit比 13 | #你能让我亏本,说明你的价格足够低,我以你为起点,重仓加持,后续很可能赚更多 14 | #就算你之后一路走低,我也有曾经的最大利润profit 15 | last = max(0, last + prices[i] - prices[i-1]) 16 | profit = max(profit, last) 17 | return profit 18 | 19 | 20 | 21 | 22 | def maxProfit(self, prices): 23 | inf = int(1e9) 24 | minprice = inf 25 | maxprofit = 0 26 | for price in prices: 27 | minprice = min(price, minprice) 28 | maxprofit = max(price - minprice, maxprofit) 29 | 30 | return maxprofit 31 | -------------------------------------------------------------------------------- /数组/122.买卖股票的最佳时机 II: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def maxProfit(self, prices): 3 | #第i天的总收益 4 | last = 0 5 | #当前情况下之前曾出现过的最高收益,不需要了 6 | # profit = 0 7 | for i in range(1,len(prices)): 8 | #每新来一个价格,只要让我当天亏了,我就在前一天卖出,再把你买入 9 | #即把每一个正项的,有益的差值都加在身上 10 | last = max(last, last + prices[i] - prices[i-1]) 11 | #不需要记录曾经最大值了,因为last一直是目前的最大值 12 | # profit = max(profit, last) 13 | return last 14 | -------------------------------------------------------------------------------- /数组/1266.访问所有的的最小时间: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def minTimeToVisitAllPoints(self, points): 3 | """ 4 | :type points: List[List[int]] 5 | :rtype: int 6 | """ 7 | #很巧妙的思路 8 | #先存下起点的横纵坐标 9 | x0, x1 = points[0] 10 | #需要的时间 11 | ans = 0 12 | #从第二个点开始循环 13 | for i in range(1, len(points)): 14 | y0, y1 = points[i] 15 | #从一个点到另一个点的时间由Δx和Δy的最大值决定,即切比雪夫距离 16 | #只要一心走差值最大的一边即可,另一边要走的话适时加入对角线走法即可 17 | #因为对角线就是即走了x又走了y 18 | ans += max(abs(x0 - y0), abs(x1 - y1)) 19 | x0, x1 = points[i] 20 | return ans 21 | -------------------------------------------------------------------------------- /数组/136.只出现一次的数字: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def singleNumber(self, nums): 3 | """ 4 | :type nums: List[int] 5 | :rtype: int 6 | """ 7 | #运用异或的性质,相同的两个数异或为0,0和任何数异或,结果为任何数 8 | a = 0 9 | #因为所有元素中只有一个是单个的,剩下的都是成对出现的 10 | #成对出现的元素累积异或,结果为0,0和剩下的哪个元素异或,得到结果 11 | for i in nums: 12 | a = a ^ i 13 | return a 14 | -------------------------------------------------------------------------------- /数组/167.两数之和 II - 输入有序数组: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def twoSum(self, numbers, target): 3 | """ 4 | :type numbers: List[int] 5 | :type target: int 6 | :rtype: List[int] 7 | """ 8 | '''mymethod 9 | #同向双指针,时间复杂度n^2,相对于暴力求解,只改善了常数项。当数组无穷大时,相当于没改善 10 | #对于循环来说,不管是从头到尾遍历,还是只循环部分,一次循环的时间复杂度都是n 11 | #因为当数组无穷大时,遍历一遍和只循环部分都是无穷大,无穷大的常数分之一还是无穷大 12 | #算时间复杂度按最坏情况算 13 | #本题循环中,慢指针i走一步,j遍历一回。最坏情况是j一直没找到,遍历到结束 14 | #这样的话,如果数组长度为n,那么j一共遍历了n回,因为i每回都向前移一步, 15 | #所以j每回都少访问一个元素,直到最后一次循环j只访问一个元素, 16 | #也就是说j相当于每回访问n/2个元素,一共循环了n回,总共访问n*(n/2)个元素 17 | #类似于一个矩形沿对角线被砍成了直角三角形 18 | #虽然极大减少了访问元素的数量,但n无穷大时,n/2和n没有区别,n*(n/2)相当于n^2 19 | #所以时间复杂度不变 20 | i = 0 #慢指针 21 | j = 1 #快指针 22 | while True: 23 | #如果等于目标值,直接返回 24 | if numbers[i] + numbers[j] == target and i < j: 25 | return [i+1,j+1] 26 | 如果大于目标值,慢指针i向前移一位,快指针回到慢指针身边 27 | if numbers[i] + numbers[j] > target: 28 | i += 1 29 | j = i 30 | continue 31 | 如果快指针走到头依然没结果,同样,慢指针i向前移一位,快指针回到慢指针身边 32 | if j == len(numbers)-1: 33 | i += 1 34 | j = i 35 | #每次前进的快指针 36 | j +=1 37 | ''' 38 | 39 | 40 | #newmethod 41 | #反向双指针 42 | i = 0 #左指针 43 | j = len(numbers)-1 #右指针 44 | while True: 45 | #如果比目标值小,左指针+1 46 | if numbers[i] + numbers[j] < target: 47 | i += 1 48 | #如果比目标值大,右指针-1 49 | if numbers[i] + numbers[j] > target: 50 | j -= 1 51 | #如果相等,返回结果 52 | if numbers[i] + numbers[j] == target: 53 | return [i+1, j+1] 54 | #最坏情况下,每个元素都被遍历一遍,时间复杂度为n 55 | -------------------------------------------------------------------------------- /数组/169.多数元素: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def majorityElement(self, nums): 3 | """ 4 | :type nums: List[int] 5 | :rtype: int 6 | """ 7 | #这题正常思路就是这样, 8 | #还有一些牛逼解法和傻逼解法,这不重要 9 | #注意理解哈希和字典的不同 10 | a = {} 11 | for i in nums: 12 | #如果字典里没这个数,就安排上 13 | if a.get(str(i)) is None: 14 | a.update({str(i):1}) 15 | #如果有,就数量+1 16 | else: 17 | a[str(i)] += 1 18 | #达到众数要求标准可退出 19 | if a.get(str(i)) > len(nums)/2: 20 | return i 21 | 22 | 23 | #哈希和字典的区别 24 | #http://www.360doc.com/content/17/1108/12/541242_702028503.shtml 25 | -------------------------------------------------------------------------------- /数组/189.旋转数组: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def rotate(self, nums, k): 3 | """ 4 | :type nums: List[int] 5 | :type k: int 6 | :rtype: None Do not return anything, modify nums in-place instead. 7 | """ 8 | #可以理解为一排同学换座位 9 | #第0个位置同学要换到第k个位置,第k个位置的同学被挤出去,去坐第k+k个位置 10 | #这样下来走一圈有可能会回到第0个位置,而期间有的同学没换过位置 11 | #如果转一圈回来没有回到第0个位置,证明可以多转几次让所有同学都换座位 12 | #但是一旦又回到第0个位置,说明这是一个圈,再走下去只会重复让已经换过座位的同学再 13 | #所以要判断,如果要回到原点了,就把起始位置设为第1个位置从第一个位置开始继续换 14 | #一共有多少个同学,总共换多少次即可 15 | 16 | 17 | start = 0 #记录转一圈回来后,又回到的位置 18 | i = 0 #目前位置 19 | x = 0 #要去的位置 20 | temp = nums[start] #替换变量,存最开始想要换位置的同学 21 | for index in range(len(nums)): #有几个同学换几次 22 | x = (i + k)%len(nums) #目标位置 23 | temp,nums[x] = nums[x],temp #交换 24 | #交换完成,本次就算完事了,后面是为下一次交换做准备 25 | #如果已经执行到最后了,再为下一次准备就会溢出 26 | if index == len(nums) - 1: 27 | break 28 | if x == start: #如果要回到原点了 29 | #就定位到之前刚开始原点的后一个 30 | start += 1 31 | #替换变量也要存上最开始要换的同学 32 | temp = nums[start] 33 | i = start 34 | #保持住,就不往后执行了 35 | continue 36 | #通常情况就往后移 37 | i = x 38 | return nums 39 | -------------------------------------------------------------------------------- /数组/217.存在重复元素: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def containsDuplicate(self, nums): 3 | """ 4 | :type nums: List[int] 5 | :rtype: bool 6 | """ 7 | if len(set(nums)) != len(nums): 8 | return True 9 | else: 10 | return False 11 | 12 | -------------------------------------------------------------------------------- /数组/219.存在重复元素2: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def containsNearbyDuplicate(self, nums, k): 3 | """ 4 | :type nums: List[int] 5 | :type k: int 6 | :rtype: bool 7 | """ 8 | #一个空字典 9 | dic1 = {} 10 | #因为要找到是否存在重复,所以必须要遍历一次 11 | for i in range(len(nums)): 12 | #字典键为列表的值,值为列表的索引,如果为空,添加该键值对 13 | if dic1.get(nums[i]) is None: 14 | dic1[nums[i]] = i 15 | else: 16 | #如果不为空,先判断一下之前的索引是否符合要求 17 | if i - dic1[nums[i]] <= k: 18 | return True 19 | #不符合的话就更新值,继续循环 20 | else: 21 | dic1[nums[i]] = i 22 | return False 23 | -------------------------------------------------------------------------------- /数组/268.缺失的数字: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def missingNumber(self, nums): 3 | """ 4 | :type nums: List[int] 5 | :rtype: int 6 | """ 7 | nums.sort() 8 | if len(nums) == 0: 9 | return None 10 | if nums[len(nums)-1] != len(nums): 11 | return len(nums) 12 | if nums[0] != 0: 13 | return 0 14 | for i in range(1,len(nums)): 15 | if nums[i] - nums[i-1] != 1: 16 | return nums[i]-1 17 | return None 18 | -------------------------------------------------------------------------------- /数组/414.第三大的数: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def thirdMax(self, nums): 3 | """ 4 | :type nums: List[int] 5 | :rtype: int 6 | """ 7 | # nums = list(set(nums)) 8 | # nums.sort() 9 | # if len(nums) < 3: 10 | # return nums[-1] 11 | # else: 12 | # return nums[-3] 13 | if len(nums) == 1: 14 | return nums[0] 15 | else: 16 | a = float("-inf") 17 | b = float("-inf") 18 | c = float("-inf") 19 | flag = 0 20 | for i in nums: 21 | if i == a or i == b or i == c: 22 | continue 23 | if i > a: 24 | c = b 25 | b = a 26 | a = i 27 | elif i > b: 28 | c = b 29 | b = i 30 | continue 31 | elif i > c: 32 | c = i 33 | if c == float("-inf"): 34 | return a 35 | else: 36 | return c 37 | -------------------------------------------------------------------------------- /数组/448.找到所有数组中消失的数字: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def findDisappearedNumbers(self, nums): 3 | """ 4 | :type nums: List[int] 5 | :rtype: List[int] 6 | """ 7 | '''mymethod 8 | #由于存在判断是要把列表遍历一遍,所以,在列表循环中用存在判断时间复杂度会变n^2 9 | a = [] 10 | s = [] 11 | #先给出全的列表 12 | for i in range(1,len(nums)+1): 13 | a.append(i) 14 | print(a) 15 | for i in a: 16 | #判断全的列表中,那个元素是nums中没有的,没有就添加到新列表中,最后返回新列表 17 | if not i in nums: 18 | s.append(i) 19 | return s 20 | ''' 21 | 22 | #newmethod 23 | #先给出全的列表,列表的索引减一为列表的值 24 | a = [] 25 | for i in range(1,len(nums)+1): 26 | a.append(i) 27 | #如果nums的元素值在全列表里有,就把全列表里这个值改为*, 28 | #最后剩下的不是*的就是nums里没有的 29 | for i in nums: 30 | a[i-1] = '*' 31 | s = [] 32 | for i in a: 33 | if i !='*': 34 | s.append(i) 35 | return s 36 | -------------------------------------------------------------------------------- /数组/485.最大连续1的个数: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def findMaxConsecutiveOnes(self, nums): 3 | """ 4 | :type nums: List[int] 5 | :rtype: int 6 | """ 7 | max = 0 #最大连续长度 8 | x = 0 #当前连续长度 9 | for i in range(len(nums)): 10 | #如果新来的是1 11 | if nums[i] == 1: 12 | x += 1 13 | if x > max: 14 | max = x 15 | #如果不是 16 | else: 17 | if x > max: 18 | max = x 19 | x = 0 20 | return max 21 | -------------------------------------------------------------------------------- /数组/509.斐波那契数: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def fib(self, N): 3 | """ 4 | :type N: int 5 | :rtype: int 6 | """ 7 | #简单问题 8 | #设置j,k充当前一二项 9 | j = 0 10 | k = 1 11 | #如果N为0就第一项 12 | if N == 0: 13 | return j 14 | elif N == 1: 15 | #N为1就第二项 16 | return k 17 | #其他情况才能用公式 18 | else: 19 | #如何确定是N+1呢,想一下,N=3时,只循环一回 20 | for i in range(2,N+1): 21 | i = j + k 22 | j = k 23 | k = i 24 | return k 25 | 26 | -------------------------------------------------------------------------------- /数组/532. 数组中的K-diff数对: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def findPairs(self, nums, k): 3 | """ 4 | :type nums: List[int] 5 | :type k: int 6 | :rtype: int 7 | """ 8 | '''mymethod 9 | #时间复杂度太高,不好 10 | # a = [] 11 | # if k < 0: 12 | # return 0 13 | # for i in range(len(nums)-1): 14 | # for j in range(i+1,len(nums)): 15 | # if nums[i] - nums[j] == k or nums[i] - nums[j] == -k: 16 | # if [nums[i],nums[j]] not in a and [nums[j],nums[i]] not in a: 17 | # a.append([nums[i],nums[j]]) 18 | # return len(a) 19 | ''' 20 | #newmethod 21 | #应对测试里的奇葩用例 22 | if k < 0: 23 | return 0 24 | #saw存放无重复的已遍历元素 25 | #diff存放符合要求数对的较小的元素 26 | saw,diff = set(),set() 27 | for i in nums: 28 | #两个判断用来将所有符合要求数对中的较小元素找出来 29 | if i - k in saw: 30 | diff.add(i-k) 31 | if i + k in saw: 32 | diff.add(i) 33 | #对saw的添加只能放在判断后,因为如果放在判断前,就会判断到该数本身 34 | saw.add(i) 35 | return len(diff) 36 | -------------------------------------------------------------------------------- /数组/561.数组拆分: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def arrayPairSum(self, nums): 3 | """ 4 | :type nums: List[int] 5 | :rtype: int 6 | """ 7 | #先排序,再取两个里面较小的 8 | nums.sort() 9 | max = 0 10 | for i in range(0,len(nums)-1,2): 11 | max += min(nums[i],nums[i+1]) 12 | return max 13 | -------------------------------------------------------------------------------- /数组/566.重塑矩阵: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def matrixReshape(self, nums, r, c): 3 | """ 4 | :type nums: List[List[int]] 5 | :type r: int 6 | :type c: int 7 | :rtype: List[List[int]] 8 | """ 9 | '''mymethod 10 | #如果不能恰好放下,就无法变化 11 | if r * c != len(nums)*len(nums[0]): 12 | return nums 13 | else: 14 | a = [] #存放nums中所有元素到一个一维列表 15 | b = [] #存放每个子列表 16 | d = [] #最终结果 17 | #先做好a 18 | for i in range(len(nums)): 19 | for j in range(len(nums[i])): 20 | a.append(nums[i][j]) 21 | #x用于计a的下标索引 22 | x = 0 23 | for i in range(r): 24 | for j in range(c): 25 | #制作子列表 26 | d.append(a[x]) 27 | x += 1 28 | #添加子列表到结果列表中 29 | b.append(d) 30 | #清空子列表,进行下一次制作 31 | d = [] 32 | return b 33 | #时间复杂度太高,不好 34 | ''' 35 | #newmethod 36 | if len(nums)*len(nums[0])!=r*c: 37 | return nums 38 | #用于把矩阵中所有的元素化为一列列表 39 | l=[] 40 | #返回结果 41 | new=[] 42 | #列表是可以拼接的 43 | for i in range(len(nums)): 44 | l+=nums[i] 45 | #依次循环,用每行的列数c来表示步长,截取指定长度列表,添加到new中 46 | for i in range(0,len(l),c): 47 | new.append(l[i:i+c]) 48 | return new 49 | -------------------------------------------------------------------------------- /数组/605.种花问题: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def canPlaceFlowers(self, flowerbed, n): 3 | """ 4 | :type flowerbed: List[int] 5 | :type n: int 6 | :rtype: bool 7 | """ 8 | num = 0 #用于统计一共可以加几朵花 9 | count = 0 #用于记录连续为零的长度,逢3置0 10 | i = 0 #下标 11 | #用于解决开头两个0,结尾两个0的特殊入选情况,就都给它们加个0,让他们入选 12 | flowerbed = [0] + flowerbed + [0] 13 | while i < len(flowerbed): 14 | #如果是0,count自加 15 | if flowerbed[i] == 0: 16 | count += 1 17 | #遇到1,count就置0 18 | if flowerbed[i] == 1: 19 | count = 0 20 | #连续三个0,可以在中间种一朵花,count清零, 21 | if count == 3: 22 | num += 1 23 | count = 0 24 | #同时这朵花左边的空地也可能充当下一朵花右边的空地 25 | #所以i也减一 26 | #也可以给中间置1,不再给i减一,两种方法都可以 27 | i -= 1 28 | i += 1 29 | if num < n: 30 | return False 31 | else: 32 | return True 33 | -------------------------------------------------------------------------------- /数组/628.三个数的最大乘积: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def maximumProduct(self, nums): 3 | """ 4 | :type nums: List[int] 5 | :rtype: int 6 | """ 7 | #先排序 8 | nums.sort() 9 | #会发现,三数相乘取最大,如果结果是正数,只有两种情况,三个最大正数相乘或者 10 | #一个最大正数和两个最小负数相乘 11 | #如果结果是负数,说明最大的数都是负数,只是在负数中挑三个最接近0的 12 | 13 | #如果所有的数都小于0,就最后三个最大的相乘 14 | if nums[-1] < 0: 15 | return nums[-1]*nums[-2]*nums[-3] 16 | #如果倒数第一个数大于等于0,就用倒数第一个数乘最小的两个数 17 | if nums[-1] >= 0 and nums[-2] < 0 and nums[-3] < 0: 18 | return nums[0]*nums[1]*nums[-1] 19 | #如果倒数一二都大于等于0,就倒数第一个和最小的两个数相乘 20 | if nums[-1] >= 0 and nums[-2] >= 0 and nums[-3] < 0: 21 | return nums[0]*nums[1]*nums[-1] 22 | #如果最大的三个都大于0,就从最大三个,和,最后一个与前两个最小的相乘,中选一个最大的 23 | if nums[-3] >= 0: 24 | return max(nums[-1]*nums[-2]*nums[-3],nums[0]*nums[1]*nums[-1]) 25 | #再思考一下,其实排好序后,只用比较 26 | #nums[-1]*nums[-2]*nums[-3]和nums[0]*nums[1]*nums[-1])谁更大即可 27 | #根本不用分那么多情况 28 | #再思考,其实排序也不需要,只要找到最大的三个数和最小的两个数就好了 29 | -------------------------------------------------------------------------------- /数组/643.子数组最大平均数1: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def findMaxAverage(self, nums, k): 3 | """ 4 | :type nums: List[int] 5 | :type k: int 6 | :rtype: float 7 | """ 8 | sum = 0 #用于记录最大连续和 9 | #把窗体填满 10 | for i in range(k): 11 | sum += float(nums[i]) 12 | #temp是用于交换的变量 13 | temp = sum 14 | #i在前,j断后 15 | j = 0 16 | #从第一次填满窗口后开始遍历 17 | for i in range(k,len(nums)): 18 | #加上新头部,减去旧尾部 19 | temp += nums[i] 20 | temp -= nums[j] 21 | j += 1 22 | #如果最新的窗口比原来大,那就让sum存储最新的,否则sum依然拿之前最大的 23 | if temp > sum: 24 | sum = temp 25 | return float(sum/k) 26 | -------------------------------------------------------------------------------- /数组/661.图片平滑器: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def imageSmoother(self, M): 3 | """ 4 | :type M: List[List[int]] 5 | :rtype: List[List[int]] 6 | """ 7 | #又臭又长的代码 8 | #sum存周围数的累加 9 | sum = 0 10 | #累加一个数,count自加 11 | count = 0 12 | #标记上下左右是否是边界 13 | up = False 14 | down = False 15 | left = False 16 | right = False 17 | #用于建立一个等大的空矩阵 18 | newM1 = [] 19 | newM2 = [] 20 | for i in range(len(M)): 21 | for j in range(len(M[0])): 22 | newM1.append(None) 23 | newM2.append(newM1) 24 | #加完一行记得把newM1置空 25 | newM1 = [] 26 | for i in range(len(M)): 27 | for j in range(len(M[i])): 28 | #判断是否有上下左右,左上左下,右上右下 29 | if i == 0: 30 | up = True 31 | if i == len(M)-1: 32 | down = True 33 | if j == 0: 34 | left = True 35 | if j == len(M[i])-1: 36 | right = True 37 | if up is not True: 38 | sum += M[i-1][j] 39 | count += 1 40 | if down is not True: 41 | sum += M[i+1][j] 42 | count += 1 43 | if left is not True: 44 | sum += M[i][j-1] 45 | count += 1 46 | if right is not True: 47 | sum += M[i][j+1] 48 | count += 1 49 | if up is not True and left is not True: 50 | sum += M[i-1][j-1] 51 | count += 1 52 | if up is not True and right is not True: 53 | sum += M[i-1][j+1] 54 | count += 1 55 | if down is not True and left is not True: 56 | sum += M[i+1][j-1] 57 | count += 1 58 | if down is not True and right is not True: 59 | sum += M[i+1][j+1] 60 | count += 1 61 | #再加上本身 62 | sum += M[i][j] 63 | count += 1 64 | newM2[i][j] = sum//count 65 | #循环一次后初始化 66 | sum = 0 67 | count = 0 68 | up = False 69 | down = False 70 | left = False 71 | right = False 72 | return newM2 73 | -------------------------------------------------------------------------------- /数组/665.非递减数列: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def checkPossibility(self, nums): 3 | """ 4 | :type nums: List[int] 5 | :rtype: bool 6 | """ 7 | #复制一个nums 8 | numscopy = nums[:] 9 | #判断靠右行不行 10 | flag1 = True 11 | #判断靠左行不行 12 | flag2 = True 13 | #靠右试一试,不行flag1给False 14 | for i in range(len(nums) - 1): 15 | if nums[i] > nums[i + 1]: 16 | nums[i] = nums[i+1] 17 | break 18 | for i in range(len(nums) - 1): 19 | if nums[i] > nums[i + 1]: 20 | flag1 = False 21 | #nums归位,试试靠左行不行,不行flag2给False 22 | nums = numscopy[:] 23 | for i in range(1,len(nums)): 24 | if nums[i] < nums[i - 1]: 25 | nums[i] = nums[i - 1] 26 | break 27 | for i in range(len(nums) - 1): 28 | if nums[i] > nums[i + 1]: 29 | flag2 = False 30 | #如果都不行,返回False 31 | if flag1 is False and flag2 is False: 32 | return False 33 | else: 34 | return True 35 | -------------------------------------------------------------------------------- /数组/667.优美的排列2: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def constructArray(self, n, k): 3 | """ 4 | :type n: int 5 | :type k: int 6 | :rtype: List[int] 7 | """ 8 | #纯找规律 9 | #先把列表整出来,用于挑选元素到numsc中 10 | nums = [] 11 | for i in range(n): 12 | nums.append(i+1) 13 | #复制一份,用于存放结果 14 | numsc = nums[:] 15 | #用于正负变换 16 | change = -1 17 | #用于存每次要从nnums的哪个下标中取,刚开始a=k 18 | a = k 19 | for i in range(1,len(nums)): 20 | #如果k减到0了,就退出 21 | if k == 0: 22 | break 23 | numsc[i] = nums[a] 24 | #开始准备下一次的a 25 | #规律:假设数组是[1,2,3,4,5],k为4,因为要有4个不同的差值, 26 | #其实就是4,3,2,1这四个 27 | #开头的1不动,下一个为5,才能和1差4,再下一个为2,才能和5差3, 28 | #再下一个是4,才能和2差2,再下一个是3,才能和4差1,而且是一正一负的 29 | #即新数组是[1,5,2,4,3] 30 | #从5开始,下标是4,1,3,2 31 | #4和1差3,正的。1和3差2,负的。3和2差1,正的。 32 | #可看出第一个变换的元素,即1后边的元素的下标一定是原始列表的第k个, 33 | #然后依次按正负缩小差距 34 | a = a + change * (k-1) 35 | k -= 1 36 | change = change*(-1) 37 | return numsc 38 | -------------------------------------------------------------------------------- /数组/674.最长连续递增序列: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def findLengthOfLCIS(self, nums): 3 | """ 4 | :type nums: List[int] 5 | :rtype: int 6 | """ 7 | #如果没数,则0 8 | if len(nums) == 0: 9 | return 0 10 | #只要有数,至少是1 11 | maxcount = 1 #历史最大长度 12 | count = 1 #当前长度 13 | for i in range(len(nums)-1): 14 | #如果小于后一个元素,则count自加 15 | if nums[i] < nums[i+1]: 16 | count += 1 17 | else: 18 | #如果不是,则和当前的连续递增列结束了,把它的长度和历史最大长度比较,谁大取谁 19 | #如果想不通此时应不应该给count自加一下再和maxcount比较,可以举例子 20 | maxcount = max(maxcount,count) 21 | count = 1 22 | return max(maxcount,count) 23 | -------------------------------------------------------------------------------- /数组/两数之和: -------------------------------------------------------------------------------- 1 | '''给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 2 | 3 | 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 4 | 5 | 示例: 6 | 7 | 给定 nums = [2, 7, 11, 15], target = 9 8 | 9 | 因为 nums[0] + nums[1] = 2 + 7 = 9 10 | 所以返回 [0, 1] 11 | ''' 12 | 13 | class Solution(object): 14 | def twoSum(self, nums, target): 15 | """ 16 | :type nums: List[int] 17 | :type target: int 18 | :rtype: List[int] 19 | """ 20 | 21 | ''' 22 | my_method 23 | one = 0 24 | two = 0 25 | for i in nums: 26 | for j in nums: 27 | if i + j == target and one != two: 28 | return [one,two] 29 | break 30 | two += 1 31 | two = 0 32 | one += 1 33 | ''' 34 | 35 | 36 | #先空字典 37 | dct = {} 38 | #通过枚举方法拿到下标和数据 39 | for i, n in enumerate(nums): 40 | #如果目标值减得到值在字典里,就返回这个键值对的键和本次循环的下标i 41 | if target - n in dct: 42 | return [dct[target - n], i] 43 | #如果不在字典里,就把本次循环拿到的值n当键,下标i当值,存入字典 44 | dct[n] = i 45 | #速度快是因为一次循环,且用键值对直接匹配,不用遍历,直接通过关键字key得到要存取的记录内存存储位置 46 | 47 | 48 | #哈希是什么,为什么快? 49 | #https://www.cnblogs.com/acm-bingzi/p/hash.html 50 | #哈希查找 51 | #https://blog.csdn.net/weixin_41362649/article/details/81865829 52 | -------------------------------------------------------------------------------- /数组/删除排序数组中的重复项: -------------------------------------------------------------------------------- 1 | # 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。 2 | # 3 | # 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。 4 | # 5 | # 示例 1: 6 | # 7 | # 给定数组 nums = [1,1,2], 8 | # 9 | # 函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。 10 | # 11 | # 你不需要考虑数组中超出新长度后面的元素。 12 | # 示例 2: 13 | # 14 | # 给定 nums = [0,0,1,1,1,2,2,3,3,4], 15 | # 16 | # 函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。 17 | # 18 | # 你不需要考虑数组中超出新长度后面的元素。 19 | 20 | 21 | 22 | 23 | class Solution(object): 24 | def removeDuplicates(self, nums): 25 | """ 26 | :type nums: List[int] 27 | :rtype: int 28 | """ 29 | #注意,数组是有序的,所以不会出现不连续的重复数字 30 | #我们需要用到同向双指针算法,首先将数组排序,这样哪些重复的整数就会被挤在一起。 31 | #然后用两根指针,一根指针走得 32 | #快一些遍历整个数组,另外一根指针,一直指向当前不重复部分的最后一个数。快指针发现一个和慢指针指向的数不 33 | #同的数之后,就可以把这个数丢到慢指针后面的一个位置,并把慢指针 ++ 34 | #另一种描述: 35 | #遍历的索引当作快指针,设定index变量当作慢指针。 36 | #两指针的元素两两比较, 37 | #如果不相同快指针索引+1,慢指针索引+1,快指针对应的索引的元素替换为慢指针元素 38 | #如果相同,快指针索引+1,慢指针索引不变。 39 | #两指针之间的对应的索引元素都是重复的!index慢索引及之前索引元素都是不重复的。 40 | i = 0 41 | for num in nums: 42 | #若输入[1,2,2,3] 43 | #第一回循环nums[0] == nums[0],什么都不做 44 | #第二回nums[0] != nums[1],执行内容,nums[1] = nums[1] 45 | #第三回nums[1] == nums[2],什么都不做 46 | #第四回nums[1] != nums[3],则执行内容nums[2] == nums[3] 47 | #最后返回i+1 48 | if nums[i] != num: 49 | i += 1 50 | nums[i] = num 51 | return i+1 52 | #什么是双指针? 53 | #https://www.e-learn.cn/content/qita/2295183 54 | -------------------------------------------------------------------------------- /数组/合并两个有序数组: -------------------------------------------------------------------------------- 1 | #第88道 2 | class Solution(object): 3 | def merge(self, nums1, m, nums2, n): 4 | """ 5 | :type nums1: List[int] 6 | :type m: int 7 | :type nums2: List[int] 8 | :type n: int 9 | :rtype: None Do not return anything, modify nums1 in-place instead. 10 | """ 11 | '''mymethod 12 | j = 0 13 | #先合并两个数组 14 | for i in range(m, len(nums1)): 15 | nums1[i] = nums2[j] 16 | j += 1 17 | #再用冒泡排序 18 | for i in range(len(nums1)): 19 | for j in range(len(nums1) - i - 1): 20 | if nums1[j] >= nums1[j + 1]: 21 | nums1[j], nums1[j + 1] = nums1[j + 1], nums1[j] 22 | return nums1 23 | #但题目的意图明显不是这样,应该善用有序数组这个条件,所以这不是个好方法 24 | ''' 25 | 26 | 27 | 28 | #因为最后要返回nums1,但又要用目前nums1中的数据,所以copy一个出来用 29 | nums1_copy = nums1[:m] 30 | nums1[:] = [] 31 | #p1是nums1的指针 32 | #p2是nums2的指针 33 | p1 = 0 34 | p2 = 0 35 | #遍历到其中较短的那个结束为止 36 | while p1 < m and p2 < n: 37 | #谁更小谁就放入nums1 38 | if nums1_copy[p1] < nums2[p2]: 39 | nums1.append(nums1_copy[p1]) 40 | p1 += 1 41 | else: 42 | nums1.append(nums2[p2]) 43 | p2 += 1 44 | #因为不知道谁会先结束,也就不知道谁还没遍历完,就把两种情况都判断一下 45 | #因为有序,所以直接加上即可 46 | if p1 < m: 47 | nums1[p1 + p2:] = nums1_copy[p1:] 48 | if p2 < n: 49 | nums1[p1 + p2:] = nums2[p2:] 50 | -------------------------------------------------------------------------------- /数组/搜索插入位置: -------------------------------------------------------------------------------- 1 | #第35题 2 | class Solution(object): 3 | def searchInsert(self, nums, target): 4 | """ 5 | :type nums: List[int] 6 | :type target: int 7 | :rtype: int 8 | """ 9 | 10 | #运用二分法的思想,类似于猜数字 11 | #i为左范围,j为右范围 12 | i = 0 13 | j = len(nums) - 1 14 | #边界问题很讨厌,在最前面解决掉 15 | #这三句防止了数组里只有一个元素,以及只有两个元素的情况下,前后指针不能动的情况 16 | #也防止了target比数组最大值大,最小值小的尖锐情况 17 | #最终通过while循环得到的结果,都是分别执行过两个比大小判断至少一次的数据 18 | if target <= nums[0]: 19 | return 0 20 | if target == nums[j]: 21 | return j 22 | if target > nums[j]: 23 | return j + 1 24 | while True: 25 | #如果target比中位数小,则右边界换为中位数 26 | if target < nums[int((i + j) / 2)]: 27 | j = int((i + j) / 2) 28 | #如果target比中位数大,则左边界换位中位数 29 | if target > nums[int((i + j) / 2)]: 30 | i = int((i + j) / 2) 31 | #如果刚好和中位数相等,输出索引位置即可 32 | if target == nums[int((i + j) / 2)]: 33 | return int((i + j) / 2) 34 | #经过循环前的判断,现在已经不可能出现i,j重合,他们之间会止步在相差1,此时,说明数组里没有与target相等的,且target在i和j之间 35 | if (j - i) == 1: 36 | return j 37 | #这个思路很棒,但还可以在此基础上简化,在循环体中就处理边界问题 38 | -------------------------------------------------------------------------------- /数组/数组加一: -------------------------------------------------------------------------------- 1 | # 给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。 2 | # 3 | # 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。 4 | # 5 | # 你可以假设除了整数 0 之外,这个整数不会以零开头。 6 | # 7 | # 示例 1: 8 | # 9 | # 输入: [1,2,3] 10 | # 输出: [1,2,4] 11 | # 解释: 输入数组表示数字 123。 12 | # 示例 2: 13 | # 14 | # 输入: [4,3,2,1] 15 | # 输出: [4,3,2,2] 16 | # 解释: 输入数组表示数字 4321。 17 | 18 | 19 | 20 | class Solution(object): 21 | def plusOne(self, digits): 22 | """ 23 | :type digits: List[int] 24 | :rtype: List[int] 25 | """ 26 | ''' 27 | mymethod 28 | a = '' 29 | list1 =[] 30 | for i in digits: 31 | a += str(i) 32 | a = int(a) 33 | a += 1 34 | a = str(a) 35 | for i in a: 36 | list1.append(int(i)) 37 | return list1 38 | ''' 39 | #从后往前遍历,注意最前面是-1 40 | for i in range(len(digits)-1, -1, -1): 41 | #每次最后一位先+1 42 | digits[i] += 1 43 | #令最后一位的新值为和10取余后的值,如果+1后是10(即原来是9),现在和10取余结果为0,也就是+1后进位了,要继续往前遍历 44 | #如果+1后不是10,则没有进位,和10取余结果是其本身,直接返回就好 45 | digits[i] = digits[i] % 10 46 | if digits [i] != 0: 47 | return digits 48 | #能遍历到头,说明原来是99999... 49 | #则单独给它100000... 50 | newdigits = [0] * (len(digits)+1) 51 | newdigits[0] = 1 52 | return newdigits 53 | -------------------------------------------------------------------------------- /数组/最大子序和: -------------------------------------------------------------------------------- 1 | #第53道 2 | class Solution(object): 3 | def maxSubArray(self, nums): 4 | """ 5 | :type nums: List[int] 6 | :rtype: int 7 | """ 8 | '''mymethod 9 | #max记录以第i个元素开头的序列中最大的子序列 10 | max = nums[0] 11 | #finamax为总体最大的子序列 12 | finamax =max 13 | #sum累计求各个子序列的和 14 | sum = 0 15 | for i,n in enumerate(nums): 16 | #先给sum赋第一个元素的值,说不定第一个元素就是最大自序和呢 17 | sum = nums[i] 18 | #因为下面的j从i+1开始,这里涉及到指针越界的问题,所以在倒数第二个元素停下 19 | if i < len(nums)-1: 20 | for j in range(i+1, len(nums)): 21 | #如果目前的子序列和大于max,就交换 22 | if sum >= max: 23 | max = sum 24 | #这里放在判断后面再累加,是因为如果在判断前累加会遗漏最大子序和是单一元素的情况 25 | sum += nums[j] 26 | #如果判断后面再累加,就会在最后少判断一次,在这里补上 27 | if sum >= max: 28 | max = sum 29 | #i-1个max中找到最大的finamax 30 | if max >= finamax: 31 | finamax = max 32 | else: 33 | #以最后一个元素为开头(同时是结尾)的子序在刚开始的循环中被排除掉了,它也可能是最大子序和 34 | if nums[len(nums)-1] >= finamax: 35 | finamax = nums[len(nums)-1] 36 | return finamax 37 | ''' 38 | #采用动态规划 39 | #nums[i-1]并不是数组前一项的意思,而是到前一项为止的最大子序和 40 | #和0比较是因为只要大于0,就可以相加构造最大子序和 41 | #如果小于0则相加为0,nums[i]=nums[i],相当于最大子序和又重新计算。 42 | #其实是一边遍历一边计算最大序和 43 | for i in range(1, len(nums)): 44 | #前一项的子序和只要大于0,都是有益的,需要加上,构成最新的最大子序和 45 | #并把这个目前的最大子序和存入i中 46 | nums[i]= nums[i] + max(nums[i-1], 0) 47 | #最后返回i个当时是最大子序和的数值中的最大值 48 | return max(nums) 49 | #什么是动态规划? 50 | #https://www.cnblogs.com/caiyishuai/p/9047991.html 51 | -------------------------------------------------------------------------------- /数组/移动零到末尾: -------------------------------------------------------------------------------- 1 | #第283道 2 | class Solution(object): 3 | def moveZeroes(self, nums): 4 | """ 5 | :type nums: List[int] 6 | :rtype: None Do not return anything, modify nums in-place instead. 7 | """ 8 | ''' 9 | #这种方法其实还不错 10 | #遍历一遍,遇0弹出,末尾补0 11 | #但是似乎还能更优,用双指针试试 12 | #我似乎感觉到了我的进步。。。。 13 | sum = 0 14 | for i in range(len(nums)-1,-1,-1): 15 | if nums[i] == 0: 16 | nums.pop(i) 17 | nums.append(0) 18 | # sum += 1 19 | return nums 20 | ''' 21 | 22 | 23 | 24 | ''' 25 | #这个方法已经非常棒了,但是会发现用双指针做本题有一个特点 26 | #快指针和慢指针不在同一位置时,快指针在给慢指针赋完值后就没用了,可以直接把快指针所在元素置0 27 | #这样就不需要再while循环,把剩下的置0了 28 | i = 0 29 | for j in range(len(nums)): 30 | if nums[j] != 0: 31 | nums[i] = nums[j] 32 | i += 1 33 | while i < len(nums): 34 | nums[i] = 0 35 | i += 1 36 | return nums 37 | ''' 38 | 39 | 40 | i = 0 41 | for j in range(len(nums)): 42 | #如果快指针和慢指针在同一位置,这个位置不能被置0, 43 | #如果置0,上一步的nums[i] = nums[j]就白赋值了 44 | if nums[j] != 0 and j != i: 45 | nums[i] = nums[j] 46 | nums[j] = 0 47 | i += 1 48 | elif nums[j] != 0 and j == i: 49 | i += 1 50 | return nums 51 | -------------------------------------------------------------------------------- /数组/移除指定元素: -------------------------------------------------------------------------------- 1 | 第27道 2 | class Solution(object): 3 | def removeElement(self, nums, val): 4 | """ 5 | :type nums: List[int] 6 | :type val: int 7 | :rtype: int 8 | """ 9 | ''' 10 | #pop操作会删除一个元素后,把后面的元素自动前移,倒序的话,把删去的窟窿以后的元素往前移,对前面没有遍历过的元素不会有影响 11 | #即反向遍历不会在删除元素后继续向前移,所以不存在多个连续的重复数字漏删的问题 12 | for i in range(len(nums)-1,-1,-1): 13 | if nums[i] == val: 14 | nums.pop(i) 15 | return len(nums) 16 | #但是pop方法内部实现复杂占用内存较多,这仍不是一个好方法。 17 | ''' 18 | #最佳方法依然是双指针,快指针j在前开拓,不断将新的列表元素与val比较,与val不同的元素会交给慢指针i所在的位置 19 | #然后慢指针i+1 20 | #最后i之前的元素全是不等于val的 21 | i = 0 22 | for j, n in enumerate(nums): 23 | if nums[j] != val: 24 | nums[i] = nums[j] 25 | i += 1 26 | return i 27 | -------------------------------------------------------------------------------- /树/617. 合并二叉树: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode(object): 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution(object): 9 | def mergeTrees(self, t1, t2): 10 | """ 11 | :type t1: TreeNode 12 | :type t2: TreeNode 13 | :rtype: TreeNode 14 | """ 15 | print('qqq') 16 | #如果两节点都存在就相加 17 | #若t1,t2中出现至少一个null,则不能再继续递归,因为null不是节点,不存在left和right 18 | #这时直接返回最可能不为空的那个(有可能两个都为空) 19 | #如果有一个不为空,那正好,返回该节点,就不再递归,该节点后面的节点本来也接在该节点上, 20 | #也可能该节点后面也是null,那就无所谓了 21 | if t1 and t2 : 22 | #相加赋给t1 23 | t1.val += t2.val 24 | #向下递归 25 | t1.left = self.mergeTrees(t1.left, t2.left) 26 | t1.right = self.mergeTrees(t1.right, t2.right) 27 | #最后递归出来后,返回根节点 28 | return t1 29 | #有一个节点不存在就返回可能是节点的那个,也可能两个都是null,那就无所谓了 30 | return t1 or t2 31 | -------------------------------------------------------------------------------- /链表/206. 反转链表: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode(object): 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.next = None 6 | 7 | #法一 8 | class Solution(object): 9 | def reverseList(self, head): 10 | """ 11 | :type head: ListNode 12 | :rtype: ListNode 13 | """ 14 | #p为迭代指针,rev为结果指针 15 | 16 | #第一层循环 17 | 18 | # res:1->2->3->4->5 19 | 20 | # res:1->None 21 | 22 | # p:2->3->4->5 23 | 24 | # 第二层循环 25 | 26 | # res:2->3->4->5 27 | 28 | # res:2->1->None 29 | 30 | # p:3->4->5 31 | 32 | # 第三层循环 33 | 34 | # res:3->4->5 35 | 36 | # res:3->2->1->None 37 | 38 | # p:4->5 39 | 40 | # 第四层循环 41 | 42 | # res:4->5 43 | 44 | # res:4->3->2->1->None 45 | 46 | # p:5 47 | 48 | # 第五层循环 49 | 50 | # res:5 51 | 52 | # res:5->4->3->2->1->None 53 | 54 | # p:None 55 | 56 | # end... 57 | p, rev = head, None 58 | while p: 59 | rev, rev.next, p = p, rev, p.next 60 | return rev 61 | 62 | 63 | 64 | #法二 65 | class Solution(object): 66 | def reverseList(self, head): 67 | """ 68 | :type head: ListNode 69 | :rtype: ListNode 70 | """ 71 | # 申请两个节点,pre和 cur,pre指向None 72 | pre = None #pre要成为当前节点的next 73 | cur = head #当前节点 74 | while cur: 75 | # 这里用tmp存cur的next,也就是说tmp是cur向后遍历的排头兵,为cur保存遍历的下一个位置 76 | tmp = cur.next 77 | # 然后将当前节点指向pre,此时pre已然成为cur的next 78 | cur.next = pre 79 | # pre和cur继续向后遍历一位 80 | #pre将成为下一个cur的next,也就是当前cur 81 | pre = cur 82 | #排头兵发挥作用,cur成功后移 83 | cur = tmp 84 | return pre 85 | 86 | 87 | 88 | --------------------------------------------------------------------------------