双指针

此生再无相见时 提交于 2019-11-29 21:17:18
复制代码
数组简介

数组是一种基本的数据结构,用于按顺序存储元素的集合。但是元素可以随机存取,因为数组中的每个元素都可以通过数组索引来识别。

数组可以有一个或多个维度。这里我们从一维数组开始,它也被称为线性数组。这里有一个例子:

在上面的例子中,数组 A 中有 6 个元素。也就是说,A 的长度是 6 。我们可以使用 A[0] 来表示数组中的第一个元素。因此,A[0] = 6 。类似地,A[1] = 3,A[2] = 8,依此类推。

 
复制代码
复制代码
寻找数组的中心索引 给定一个整数类型的数组 nums,请编写一个能够返回数组“中心索引”的方法。  我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。  如果数组不存在中心索引,那么我们应该返回 -1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个。  示例 1:  输入:  nums = [1, 7, 3, 6, 5, 6] 输出: 3 解释:  索引3 (nums[3] = 6) 的左侧数之和(1 + 7 + 3 = 11),与右侧数之和(5 + 6 = 11)相等。 同时, 3 也是第一个符合要求的中心索引。 示例 2:  输入:  nums = [1, 2, 3] 输出: -1 解释:  数组中不存在满足此条件的中心索引。 说明:  nums 的长度范围为 [0, 10000]。 任何一个 nums[i] 将会是一个范围在 [-1000, 1000]的整数。
复制代码
复制代码
class Solution(object):     def pivotIndex(self, nums):         """         :type nums: List[int]         :rtype: int         """ #       思路:通过求取整个数组的和记为sum_nums,依次遍历每个元素,记为sum_left,sum_right,center,其中sum_left可通过每一次遍历得出,sum_right=sum_nums-center-sum_left         nums_len=len(nums)         sum_nums=sum(nums)         sum_left=0         for i in range(nums_len):             if i>=1:                 sum_left+=nums[i-1]             sum_right=sum_nums-nums[i]-sum_left             if sum_left==sum_right:                 return i         return -1
复制代码
至少是其他数字两倍的最大数 在一个给定的数组nums中,总是存在一个最大元素 。  查找数组中的最大元素是否至少是数组中每个其他数字的两倍。  如果是,则返回最大元素的索引,否则返回-1。  示例 1:  输入: nums = [3, 6, 1, 0] 输出: 1 解释: 6是最大的整数, 对于数组中的其他整数, 6大于数组中其他元素的两倍。6的索引是1, 所以我们返回1.    示例 2:  输入: nums = [1, 2, 3, 4] 输出: -1 解释: 4没有超过3的两倍大, 所以我们返回 -1.    提示:  nums 的长度范围在[1, 50]. 每个 nums[i] 的整数范围在 [0, 99].
复制代码

 

复制代码
复制代码
class Solution(object):     def dominantIndex(self, nums):         """         :type nums: List[int]         :rtype: int         """ #思路:对原数组取出第一个最大值,去除该最大值的数组找出第二最大*2,比较         import copy         if len(nums)<=1:             return 0         max_number=max(nums)         nums_=copy.copy(nums)         nums_.remove(max_number)         max_two_number=max(nums_)*2         if max_number>=max_two_number:             return nums.index(max_number)         return -1
复制代码
复制代码
加一 给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。  最高位数字存放在数组的首位, 数组中每个元素只存储一个数字。  你可以假设除了整数 0 之外,这个整数不会以零开头。  示例 1:  输入: [1,2,3] 输出: [1,2,4] 解释: 输入数组表示数字 123。 示例 2:  输入: [4,3,2,1] 输出: [4,3,2,2] 解释: 输入数组表示数字 4321。
复制代码
复制代码
class Solution:     def plusOne(self, digits):         """         :type digits: List[int]         :rtype: List[int]         """          #     思路:通过字符串进行连接,转int+1,在转字符串,通过循环         num=[str(i) for i in digits]         num=int(''.join(num))+1         num=str(num)         res=[]         for i in range(len(num)):             res.append(int(num[i]))         return res
复制代码
复制代码
杨辉三角 给定一个非负整数 numRows,生成杨辉三角的前 numRows 行 
 在杨辉三角中,每个数是它左上方和右上方的数的和。  示例:  输入: 5 输出: [      [1],     [1,1],    [1,2,1],   [1,3,3,1],  [1,4,6,4,1] ]
复制代码

 

复制代码
class Solution(object):     def generate(self, numRows):         """         :type numRows: int         :rtype: List[List[int]]         """                  #思路:除了第一行后其余每行都有两个1,因而将第一行单独列出来,第二行开始每行第一步添加1,然后开始计算上一行每两个数的求和,最后在进行添加1,         res=[]         if numRows==0:             return []         res.append([1])         for  i in range(1,numRows):             res.append([1])             for j in range(1,len(res[i-1])):                 res[i].append(res[i-1][j]+res[i-1][j-1])             res[i].append(1)         return res
复制代码

 

Python的每个对象都分为可变和不可变,主要的核心类型中,数字、字符串、元组是不可变的,列表、字典是可变的。  对不可变类型的变量重新赋值,实际上是重新创建一个不可变类型的对象,并将原来的变量重新指向新创建的对象(如果没有其他变量引用原有对象的话(即引用计数为0),原有对象就会被回收)。 可变对象:如果进行的是浅复制,那么存在任何一个对象修改,其他对象也会一起修改(地址相同) 不可变对象,如果进行的是浅复制,相当于深复制,地址不同
复制代码
print '可变' t=[1,3,4,1] t_copy=t t_copy.append(12) print t,t_copy,id(t),id(t_copy) m={'123':2,'sada':3} m_copy=m m['qq']=5 print m,m_copy,id(m),id(m_copy) print '不可变' k='232' k_copy=k k+='s' print k,k_copy,id(k),id(k_copy) d=10 d_copy=d d_copy+=1 print d,d_copy,id(d),id(d_copy)   输出结果:  可变 [1, 3, 4, 1, 12] [1, 3, 4, 1, 12] 140630062594024 140630062594024 {'qq': 5, 'sada': 3, '123': 2} {'qq': 5, 'sada': 3, '123': 2} 140630062705752 140630062705752 不可变 232s 232 140630062701904 140630062750056 10 11 94639729410192 94639729410168
复制代码

 

 

复制代码
list内置函数:  len(list): 列表元素个数  max(list): 列表元素最大值,但list不为空.为空报错  min(list): 列表元素最小值,但list不为空.为空报错
方法:  添加:    list.append(obj) : 在列表末尾添加新的对象    list_extend(seq):  在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)  (原地) (对于单个字符串,进行添加每个字符)    list.insert(index,obj):  将对象插入列表(原地),index超过实际长度,则添加末尾  删除:    
    list.remove(obj) :移除当前list,指定的元素,删除成功返回 None, 否则报错,(原地操作)(删除为第一个出现)      list.pop(): 根据index进行删除元素, 返回删除的元素,否则报错.(原地)      del list[index]: 删除元素,原地  查找:
    list.index(obj) :指定元素进行查找,返回其index,但不存在则报错(返回第一个出现的index)         list[index]: 指定索引进行查找,不存在报错  改:    直接对指定位置进行赋值即可  排序:    list.sort(cmp=None,key=None,reverse=False)

        cmp -- 可选参数, 如果指定了该参数会使用该参数的方法进行排序。

        key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。(主要用于元祖等,在list中存储的对象)

        reverse -- 排序规则,reverse = True 降序, reverse = False 升序(默认)。

  list.count(obj): 统计某个元素在列表中出现的次数
  list.reverse(): 对当前list进行翻转(原地)
复制代码
字符串  是一个不可变对象,内置函数和方法    http://www.runoob.com/python/python-strings.html
复制代码
 最长公共前缀 编写一个函数来查找字符串数组中的最长公共前缀。  如果不存在公共前缀,返回空字符串 ""。  示例 1:  输入: ["flower","flow","flight"] 输出: "fl" 示例 2:  输入: ["dog","racecar","car"] 输出: "" 解释: 输入不存在公共前缀。 说明:  所有输入只包含小写字母 a-z 。
复制代码
复制代码
class Solution(object):     def longestCommonPrefix(self, strs):         """         :type strs: List[str]         :rtype: str                           """ #         思路,每一次获取第一个元素的前几个字符,与其他元素的前几个字符进行比较,不相等,则返回上个长度的字符,         if strs==[]:             return ''         if len(strs)==1:             return strs[0]         for i in range(1,len(strs[0])+1):             current_str=strs[0][:i]             for j  in range(1,len(strs)):                 next_str=strs[j][:i]                 if next_str!=current_str:                     return strs[0][:i-1]                          return strs[0]
复制代码
复制代码
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回  -1。  示例 1:  输入: haystack = "hello", needle = "ll" 输出: 2 示例 2:  输入: haystack = "aaaaa", needle = "bba" 输出: -1
复制代码
复制代码
class Solution(object):     def strStr(self, haystack, needle):         """         :type haystack: str         :type needle: str         :rtype: int         """ #    思路:利用字符串中的index方法,进行寻找,不存在则通过try-except返回-1         if len(needle)==0:             return 0         try:             index_=haystack.index(needle)         except:             return -1         return index_
复制代码
复制代码
二进制求和 给定两个二进制字符串,返回他们的和(用二进制表示)。  输入为非空字符串且只包含数字 1 和 0。  示例 1:  输入: a = "11", b = "1" 输出: "100" 示例 2:  输入: a = "1010", b = "1011" 输出: "10101"
复制代码
复制代码
class Solution(object):     def addBinary(self, a, b):         """         :type a: str         :type b: str         :rtype: str         """ #         int的操作: int(t,base)  base :2为二进制, 默认为十进制   bin()  进行二进制计算 ,返回一二二进制,形如:'ob1010'         return bin(int(a,2)+int(b,2))[2:]
复制代码
复制代码
双指针技巧,它可以帮助我们解决许多与数组/字符串相关的问题https://leetcode-cn.com/explore/learn/card/array-and-string/201/two-pointer-technique/786/

总结


总之,使用双指针技巧的典型场景之一是你想要

从两端向中间迭代数组。

这时你可以使用双指针技巧:

一个指针从始端开始,而另一个指针从末端开始。

值得注意的是,这种技巧经常在排序数组中使用。

情景二:

这是你需要使用双指针技巧的一种非常常见的情况:

同时有一个慢指针和一个快指针。

解决这类问题的关键是

确定两个指针的移动策略。

与前一个场景类似,你有时可能需要在使用双指针技巧之前对数组进行排序,也可能需要运用贪心想法来决定你的运动策略。

复制代码
复制代码
反转字符串 编写一个函数,其作用是将输入的字符串反转过来。  示例 1:  输入: "hello" 输出: "olleh" 示例 2:  输入: "A man, a plan, a canal: Panama" 输出: "amanaP :lanac a ,nalp a ,nam A"
复制代码
复制代码
class Solution(object):     def reverseString(self, s):         """         :type s: str         :rtype: str         """         # return s[::-1]         # return (''.join(list(reversed(s))))                  #思路:利用双指针方法,定义左指针和右指针,依次交换元素,字符串是不可变,因为可以将其通过list转换为可变对象,然后在通过join进行连接,即可完成字符串的修改         left=0         s_list=list(s)         right=len(s_list)-1         while left<=right:             temp=s[left]             s_list[left]=s_list[right]             s_list[right]=temp             left+=1             right-=1         return ''.join(s_list)
复制代码
复制代码
两数之和 II - 输入有序数组 给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。  函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。  说明:  返回的下标值(index1 和 index2)不是从零开始的。 你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。 示例:  输入: numbers = [2, 7, 11, 15], target = 9 输出: [1,2] 解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。
复制代码
复制代码
class Solution(object):     def twoSum(self, numbers, target):         """         :type numbers: List[int]         :type target: int         :rtype: List[int]         """         n=len(numbers)         if n<2:             return []         left=0         right=n-1         while left<=right:             if numbers[left]+numbers[right]==target: #            答案是唯一的                 return [left+1,right+1]             elif numbers[left]+numbers[right]<target:                 left+=1             else:                 right-=1         return []
复制代码
情景2
复制代码
移除元素 给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。  不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。  元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。  示例 1:  给定 nums = [3,2,2,3], val = 3,  函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。  你不需要考虑数组中超出新长度后面的元素。 示例 2:  给定 nums = [0,1,2,2,3,0,4,2], val = 2,  函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。  注意这五个元素可为任意顺序。  你不需要考虑数组中超出新长度后面的元素。
复制代码
复制代码
class Solution:     def removeElement(self, nums, val):         """         :type nums: List[int]         :type val: int         :rtype: int         """         #定义双指针,使用了两个指针,i一个用于原始数组的迭代,k另一个总是指向新数组的最后一个位置         k=0         for i in range(len(nums)):             if nums[i]!=val:                 nums[k]=nums[i]                 k+=1         return k         
复制代码
复制代码
最大连续1的个数 给定一个二进制数组, 计算其中最大连续1的个数。  示例 1:  输入: [1,1,0,1,1,1] 输出: 3 解释: 开头的两位和最后的三位都是连续1,所以最大连续1的个数是 3. 注意:  输入的数组只包含 0 和1。 输入数组的长度是正整数,且不超过 10,000。
复制代码
复制代码
class Solution(object):     def findMaxConsecutiveOnes(self, nums):         """         :type nums: List[int]         :rtype: int         """         #定义双指针,一个记录其连续的次数,一个用于迭代         k=0         return_=0         for i in range(len(nums)):             if nums[i]==1:                 k+=1             else:                 return_=max(k,return_)                 k=0         return max(return_,k)
复制代码

 

复制代码
翻转字符串里的单词 给定一个字符串,逐个翻转字符串中的每个单词。  示例:    输入: "the sky is blue", 输出: "blue is sky the". 说明:  无空格字符构成一个单词。 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
复制代码
复制代码
class Solution(object):     def reverseWords(self, s):         """         :type s: str         :rtype: str         """         #思路:使用双指针,第一个指针记录不为' '的字符个数,第二个指针迭代         import re         list_s = re.split(' ', s)         prev=0         for i in range(len(list_s)):             if list_s[i] != '':                 list_s[prev]=list_s[i]                 prev+=1         del list_s[prev:]         list_s.reverse()         return ' '.join(list_s)
复制代码
复制代码
反转字符串中的单词 III 给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。  示例 1:  输入: "Let's take LeetCode contest" 输出: "s'teL ekat edoCteeL tsetnoc"  注意:在字符串中,每个单词由单个空格分隔,并且字符串中不会有任何额外的空格。
复制代码
复制代码
class Solution(object):     def reverseWords(self, s):         """         :type s: str         :rtype: str         """        #         list_s=s.split(' ')         for i in range(len(list_s)):            #下面两种形式都可以实现字符的翻转,但是不可用指针形式对字符进行赋值翻转,因为字符是不可变             # list_s[i]=''.join(reversed(list_s[i]))             list_s[i]=list_s[i][::-1]         return ' '.join(list_s)
复制代码
复制代码
删除排序数组中的重复项 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。  不要使用额外的数组空间,你必须在原地修改输入数组并在使用 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 removeDuplicates(self, nums):         """         :type nums: List[int]         :rtype: int         """ #         思路:使用双指针,一个记录不重复的元素,一个迭代         pre=0         for i in range(1,len(nums)):             if nums[i]!=nums[pre]:                 nums[pre+1]=nums[i]                 pre+=1         del nums[pre+1:]                 
复制代码
复制代码
移动零 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。  示例:  输入: [0,1,0,3,12] 输出: [1,3,12,0,0] 说明:  必须在原数组上操作,不能拷贝额外的数组。 尽量减少操作次数。
复制代码
复制代码
class Solution(object):     def moveZeroes(self, nums):         """         :type nums: List[int]         :rtype: void Do not return anything, modify nums in-place instead.         """ #    思路: 利用双指针,一个记录不为0的个数,一个迭代         pre=0         for i in range(len(nums)):             if nums[i]!=0:                 nums[pre]=nums[i]                 pre+=1         for k in range(pre,len(nums)):             nums[k]=0
复制代码

 数组练习题:

 

复制代码
643. 子数组最大平均数 I 给定 n 个整数,找出平均数最大且长度为 k 的连续子数组,并输出该最大平均数。 示例 1: 输入: [1,12,-5,-6,50,3], k = 4 输出: 12.75 解释: 最大平均数 (12-5-6+50)/4 = 51/4 = 12.75 注意: 1 <= k <= n <= 30,000。 所给数据范围 [-10,000,10,000]。https://leetcode-cn.com/problems/maximum-average-subarray-i/
复制代码
复制代码
class Solution(object):     def findMaxAverage(self, nums, k):         """         :type nums: List[int]         :type k: int         :rtype: float         """ #     思路:利用双指针,一前一后,前后差距为k         res_sum=sum_=sum(nums[:k])         left=0         right=k         while right<len(nums):             sum_-=nums[left]             sum_+=nums[right]             res_sum=max(sum_,res_sum)             left+=1             right+=1         return res_sum*1.0/k     
复制代码
复制代码
914:卡牌分组  给定一副牌,每张牌上都写着一个整数。 此时,你需要选定一个数字 X,使我们可以将整副牌按下述规则分成 1 组或更多组: 每组都有 X 张牌。 组内所有的牌上都写着相同的整数。 仅当你可选的 X >= 2 时返回 true。 示例 1:  输入:[1,2,3,4,4,3,2,1] 输出:true 解释:可行的分组是 [1,1],[2,2],[3,3],[4,4] 示例 2:  输入:[1,1,1,2,2,2,3,3] 输出:false 解释:没有满足要求的分组。 示例 3:  输入:[1] 输出:false 解释:没有满足要求的分组。 示例 4:  输入:[1,1] 输出:true 解释:可行的分组是 [1,1] 示例 5:  输入:[1,1,2,2,2,2] 输出:true 解释:可行的分组是 [1,1],[2,2],[2,2]  提示:  1 <= deck.length <= 10000 0 <= deck[i] < 10000 https://leetcode-cn.com/problems/x-of-a-kind-in-a-deck-of-cards/
复制代码
复制代码
class Solution(object):     def hasGroupsSizeX(self, deck):         """         :type deck: List[int]         :rtype: bool         """ #         思路:有题目可知,可通过dict求取每个元素 个数,并判断他们之间是否存在公约数(不为1),存在返回True,         if deck==[]:             return []         dict_={}         for i in deck:             if i not in dict_:                 dict_[i]=0             dict_[i]+=1         print dict_         num_min=min(dict_.values())         if num_min==1:             return False         for i in range(2,num_min+1):             flag=True             #对每个数字的次数进行对i求余,如果全部都为0,那么表明该全部元素之间存在公约数             for j in dict_:                 if dict_[j]%i!=0:                     flag=False             if flag==True:                 return True         return False          
复制代码

 

复制代码
941:有效的山脉数组 给定一个整数数组 A,如果它是有效的山脉数组就返回 true,否则返回 false。  让我们回顾一下,如果 A 满足下述条件,那么它是一个山脉数组:  A.length >= 3 在 0 < i < A.length - 1 条件下,存在 i 使得: A[0] < A[1] < ... A[i-1] < A[i] A[i] > A[i+1] > ... > A[B.length - 1]    示例 1:  输入:[2,1] 输出:false 示例 2:  输入:[3,5,5] 输出:false 示例 3:  输入:[0,3,2,1] 输出:true    提示:  0 <= A.length <= 10000 0 <= A[i] <= 10000  https://leetcode-cn.com/problems/valid-mountain-array/
复制代码
复制代码
class Solution(object):     def validMountainArray(self, A):         """         :type A: List[int]         :rtype: bool         """         #思路: 定义双指针,,双向遍历,前后元素满足条件则进行left  or  right 进行操作,         if len(A)<=2:             return False         left=0         right=len(A)-1         for i in range(len(A)-1):             if A[left+1]>A[left] :                 left+=1             if A[right]<A[right-1]:                 right-=1         if left!=right or right==len(A)-1 or left==0:             return False         return True
复制代码
复制代码
905:按奇偶排序数组 给定一个非负整数数组 A,返回一个由 A 的所有偶数元素组成的数组,后面跟 A 的所有奇数元素。  你可以返回满足此条件的任何数组作为答案。     示例:  输入:[3,1,2,4] 输出:[2,4,3,1] 输出 [4,2,3,1],[2,4,1,3] 和 [4,2,1,3] 也会被接受。    提示:  1 <= A.length <= 5000 0 <= A[i] <= 5000 https://leetcode-cn.com/problems/sort-array-by-parity/
复制代码
复制代码
class Solution(object):     def sortArrayByParity(self, A):         """         :type A: List[int]         :rtype: List[int]         """         odd=[]         even=[]         for i in A:             if i%2:                 odd.append(i)             else:                 even.append(i)         even.extend(odd)         return even
复制代码
复制代码
922: 按奇偶排序数据2 给定一个非负整数数组 A, A 中一半整数是奇数,一半整数是偶数。  对数组进行排序,以便当 A[i] 为奇数时,i 也是奇数;当 A[i] 为偶数时, i 也是偶数。  你可以返回任何满足上述条件的数组作为答案。     示例:  输入:[4,2,5,7] 输出:[4,5,2,7] 解释:[4,7,2,5],[2,5,4,7],[2,7,4,5] 也会被接受。    提示:  2 <= A.length <= 20000 A.length % 2 == 0 0 <= A[i] <= 1000  
复制代码
复制代码
class Solution(object):     def sortArrayByParityII(self, A):         """         :type A: List[int]         :rtype: List[int]         """         odd=[]         even=[]         res=[]         for i in A:             if i%2:                 odd.append(i)             else:                 even.append(i)         for i in range(len(A)/2):             res.append(even[i])             res.append(odd[i])         return res
复制代码
复制代码
830. 较大分组的位置 在一个由小写字母构成的字符串 S 中,包含由一些连续的相同字符所构成的分组。  例如,在字符串 S = "abbxxxxzyy" 中,就含有 "a", "bb", "xxxx", "z" 和 "yy" 这样的一些分组。  我们称所有包含大于或等于三个连续字符的分组为较大分组。找到每一个较大分组的起始和终止位置。  最终结果按照字典顺序输出。  示例 1:  输入: "abbxxxxzzy" 输出: [[3,6]] 解释: "xxxx" 是一个起始于 3 且终止于 6 的较大分组。 示例 2:  输入: "abc" 输出: [] 解释: "a","b" 和 "c" 均不是符合要求的较大分组。 示例 3:  输入: "abcdddeeeeaabbbcd" 输出: [[3,5],[6,9],[12,14]] 说明:  1 <= S.length <= 1000 https://leetcode-cn.com/problems/positions-of-large-groups/
复制代码
复制代码
class Solution(object):     def largeGroupPositions(self, S):         """         :type S: str         :rtype: List[List[int]]         """         if len(S)<=2:             return []         left=0         right=1         count=1         res=[]         #思路: 利用双指针,进行遍历,满足则count+1,不满足count-1,如果最后还满足,那么记性判断count是否大于等于3         while right<len(S):             if S[right]==S[left] and right!=len(S)-1:                 count+=1                 right+=1             elif S[right]!=S[left]:                 if count>=3:                     res.append([left,right-1])                 left=right                 right+=1                 count=1             elif S[right]==S[left] and right==len(S)-1:                 count+=1                 if count>=3:                     res.append([left,right])                 break         return res             
复制代码

 

复制代码
665. 非递减数列 给定一个长度为 n 的整数数组,你的任务是判断在最多改变 1 个元素的情况下,该数组能否变成一个非递减数列。  我们是这样定义一个非递减数列的: 对于数组中所有的 i (1 <= i < n),满足 array[i] <= array[i + 1]。  示例 1:  输入: [4,2,3] 输出: True 解释: 你可以通过把第一个4变成1来使得它成为一个非递减数列。 示例 2:  输入: [4,2,1] 输出: False 解释: 你不能在只改变一个元素的情况下将其变为非递减数列。 说明:  n 的范围为 [1, 10,000]。 https://leetcode-cn.com/problems/non-decreasing-array/
复制代码
复制代码
class Solution(object):     def checkPossibility(self, nums):         """         :type nums: List[int]         :rtype: bool         """ #    思路:通过简单的例子分析,会发现当第i个数字小于第i-1数字时,有两种替换方式,第一种是令第i个数字等于第i-1数字,另一种是第i-1数字等于第i数字.两种方式 的判别条件为i-2数字与第i个数字的比较,(也可以使用i-1与i+1进行比较,不过要注意范围)[1,3,1,2],[2,3,1,4]         flag=0         for i in range(1,len(nums)):             if nums[i]<nums[i-1]:                 flag+=1                 if flag>1:                     return False                 if i-2 < 0 or nums[i-2] <= nums[i]:                     nums[i-1] = nums[i]                 else:                     nums[i] = nums[i-1]         return True
复制代码
复制代码
628. 三个数的最大乘积 给定一个整型数组,在数组中找出由三个数组成的最大乘积,并输出这个乘积。  示例 1:  输入: [1,2,3] 输出: 6 示例 2:  输入: [1,2,3,4] 输出: 24 注意:  给定的整型数组长度范围是[3,104],数组中所有的元素范围是[-1000, 1000]。 输入的数组中任意三个数的乘积不会超出32位有符号整数的范围。 https://leetcode-cn.com/problems/maximum-product-of-three-numbers/
复制代码
复制代码
class Solution(object):     def maximumProduct(self, nums):         """         :type nums: List[int]         :rtype: int         """ #        思路:三个数的乘积最大,两种情况,第一种最大的三个数(大于0),第二种,最小的两个数(小于0)与最大的数         if len(nums)<3:             return 0         nums.sort()         return max(nums[0]*nums[1]*nums[-1],nums[-1]*nums[-2]*nums[-3])
复制代码
复制代码
896. 单调数列 如果数组是单调递增或单调递减的,那么它是单调的。  如果对于所有 i <= j,A[i] <= A[j],那么数组 A 是单调递增的。 如果对于所有 i <= j,A[i]> = A[j],那么数组 A 是单调递减的。  当给定的数组 A 是单调数组时返回 true,否则返回 false。     示例 1:  输入:[1,2,2,3] 输出:true 示例 2:  输入:[6,5,4,4] 输出:true 示例 3:  输入:[1,3,2] 输出:false 示例 4:  输入:[1,2,4,5] 输出:true 示例 5:  输入:[1,1,1] 输出:true https://leetcode-cn.com/problems/monotonic-array/
复制代码
复制代码
class Solution(object):     def isMonotonic(self, A):         """         :type A: List[int]         :rtype: bool         """         # 思路 :  对原数组进行复制,通过对原数组进行正向排序,相等返回True,不相等,有可能该原数组为逆序         if len(A)<=2:             return True         import copy         A_copy=copy.copy(A)         A.sort()         if A_copy==A:             return True         if A_copy[::-1]==A:             return True         return False
复制代码

 

复制代码
532. 数组中的K-diff数对 给定一个整数数组和一个整数 k, 你需要在数组里找到不同的 k-diff 数对。这里将 k-diff 数对定义为一个整数对 (i, j), 其中 i 和 j 都是数组中的数字,且两数之差的绝对值是 k.  示例 1:  输入: [3, 1, 4, 1, 5], k = 2 输出: 2 解释: 数组中有两个 2-diff 数对, (1, 3) 和 (3, 5)。 尽管数组中有两个1,但我们只应返回不同的数对的数量。 示例 2:  输入:[1, 2, 3, 4, 5], k = 1 输出: 4 解释: 数组中有四个 1-diff 数对, (1, 2), (2, 3), (3, 4) 和 (4, 5)。 示例 3:  输入: [1, 3, 1, 5, 4], k = 0 输出: 1 解释: 数组中只有一个 0-diff 数对,(1, 1)。 注意:  数对 (i, j) 和数对 (j, i) 被算作同一数对。 数组的长度不超过10,000。 所有输入的整数的范围在 [-1e7, 1e7]。
复制代码
复制代码
’‘’ 思路:         对原数组进行排序,然后通过双指针进行遍历,如果前后原数组在前后指针的数值相减的绝对值等于K,那么count+1,前后指针分别加1,如果大于k(表明前后指针的数组值相差过大,那么对后指针+1),否则快指针进行+1,         过程中:主要注意两个地方,1.数组对有可能存在重复,所以要对每一步生成的数组对进行记录,对重复的进行舍去。     2.后指针不能超过前指针 ,如果相等,那么对后指针进行+1处理。  ‘’‘ class Solution(object):     def findPairs(self, nums, k):         """         :type nums: List[int]         :type k: int         :rtype: int         """         nums.sort()         slow_index=0         fast_index=1         count_=0         set_=set()         while fast_index<len(nums):             if abs(nums[slow_index]-nums[fast_index])==k and nums[fast_index]+nums[slow_index] not in set_:                 set_.add(nums[fast_index]+nums[slow_index])                  slow_index+=1                 fast_index+=1                  count_+=1             elif abs(nums[slow_index]-nums[fast_index])>k:                 slow_index+=1             else:                 fast_index+=1             if slow_index==fast_index:                 fast_index+=1         return count_         
复制代码
复制代码
925. 长按键入  你的朋友正在使用键盘输入他的名字 name。偶尔,在键入字符 c 时,按键可能会被长按,而字符可能被输入 1 次或多次。  你将会检查键盘输入的字符 typed。如果它对应的可能是你的朋友的名字(其中一些字符可能被长按),那么就返回 True。     示例 1:  输入:name = "alex", typed = "aaleex" 输出:true 解释:'alex' 中的 'a' 和 'e' 被长按。 示例 2:  输入:name = "saeed", typed = "ssaaedd" 输出:false 解释:'e' 一定需要被键入两次,但在 typed 的输出中不是这样。 示例 3:  输入:name = "leelee", typed = "lleeelee" 输出:true 示例 4:  输入:name = "laiden", typed = "laiden" 输出:true 解释:长按名字中的字符并不是必要的。    提示:  name.length <= 1000 typed.length <= 1000 name 和 typed 的字符都是小写字母。
复制代码
复制代码
''' 思路:利用双指针分别遍历两个数组,对name的数组依次取出一个数,对typed数组进行遍历,如果遇到与name取出的元素相等,则推出,否则type_index+1   注意点:1.当name遍历到最后一个元素时,type是否还有元素进行遍历。   2. 避免name遍历时,type已经没有元素可以进行遍历 '''  class Solution(object):     def isLongPressedName(self, name, typed):         """         :type name: str         :type typed: str         :rtype: bool         """         name_index=0       #name的index         typed_index=0         while name_index<len(name):             char=name[name_index]             name_index+=1             if name_index==len(name) and typed_index==len(typed):   #1.避免name遍历最后一个元素时,type是否还有元素进行遍历。                 return False             #2.避免遍历时,type已经没有元素可以进行遍历             flat=False             while typed_index<len(typed):                 if char==typed[typed_index]:                     typed_index+=1                     flat=True                     break                 typed_index+=1             if not flat:                 return False         return True         
复制代码

 

0
0
« 上一篇: 二叉树的前中后遍历,层次遍历,树的递归问题(递归与迭代python)
» 下一篇: 链表(python)
复制代码
数组简介

数组是一种基本的数据结构,用于按顺序存储元素的集合。但是元素可以随机存取,因为数组中的每个元素都可以通过数组索引来识别。

数组可以有一个或多个维度。这里我们从一维数组开始,它也被称为线性数组。这里有一个例子:

在上面的例子中,数组 A 中有 6 个元素。也就是说,A 的长度是 6 。我们可以使用 A[0] 来表示数组中的第一个元素。因此,A[0] = 6 。类似地,A[1] = 3,A[2] = 8,依此类推。

 
复制代码
复制代码
寻找数组的中心索引 给定一个整数类型的数组 nums,请编写一个能够返回数组“中心索引”的方法。  我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。  如果数组不存在中心索引,那么我们应该返回 -1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个。  示例 1:  输入:  nums = [1, 7, 3, 6, 5, 6] 输出: 3 解释:  索引3 (nums[3] = 6) 的左侧数之和(1 + 7 + 3 = 11),与右侧数之和(5 + 6 = 11)相等。 同时, 3 也是第一个符合要求的中心索引。 示例 2:  输入:  nums = [1, 2, 3] 输出: -1 解释:  数组中不存在满足此条件的中心索引。 说明:  nums 的长度范围为 [0, 10000]。 任何一个 nums[i] 将会是一个范围在 [-1000, 1000]的整数。
复制代码
复制代码
class Solution(object):     def pivotIndex(self, nums):         """         :type nums: List[int]         :rtype: int         """ #       思路:通过求取整个数组的和记为sum_nums,依次遍历每个元素,记为sum_left,sum_right,center,其中sum_left可通过每一次遍历得出,sum_right=sum_nums-center-sum_left         nums_len=len(nums)         sum_nums=sum(nums)         sum_left=0         for i in range(nums_len):             if i>=1:                 sum_left+=nums[i-1]             sum_right=sum_nums-nums[i]-sum_left             if sum_left==sum_right:                 return i         return -1
复制代码
至少是其他数字两倍的最大数 在一个给定的数组nums中,总是存在一个最大元素 。  查找数组中的最大元素是否至少是数组中每个其他数字的两倍。  如果是,则返回最大元素的索引,否则返回-1。  示例 1:  输入: nums = [3, 6, 1, 0] 输出: 1 解释: 6是最大的整数, 对于数组中的其他整数, 6大于数组中其他元素的两倍。6的索引是1, 所以我们返回1.    示例 2:  输入: nums = [1, 2, 3, 4] 输出: -1 解释: 4没有超过3的两倍大, 所以我们返回 -1.    提示:  nums 的长度范围在[1, 50]. 每个 nums[i] 的整数范围在 [0, 99].
复制代码

 

复制代码
复制代码
class Solution(object):     def dominantIndex(self, nums):         """         :type nums: List[int]         :rtype: int         """ #思路:对原数组取出第一个最大值,去除该最大值的数组找出第二最大*2,比较         import copy         if len(nums)<=1:             return 0         max_number=max(nums)         nums_=copy.copy(nums)         nums_.remove(max_number)         max_two_number=max(nums_)*2         if max_number>=max_two_number:             return nums.index(max_number)         return -1
复制代码
复制代码
加一 给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。  最高位数字存放在数组的首位, 数组中每个元素只存储一个数字。  你可以假设除了整数 0 之外,这个整数不会以零开头。  示例 1:  输入: [1,2,3] 输出: [1,2,4] 解释: 输入数组表示数字 123。 示例 2:  输入: [4,3,2,1] 输出: [4,3,2,2] 解释: 输入数组表示数字 4321。
复制代码
复制代码
class Solution:     def plusOne(self, digits):         """         :type digits: List[int]         :rtype: List[int]         """          #     思路:通过字符串进行连接,转int+1,在转字符串,通过循环         num=[str(i) for i in digits]         num=int(''.join(num))+1         num=str(num)         res=[]         for i in range(len(num)):             res.append(int(num[i]))         return res
复制代码
复制代码
杨辉三角 给定一个非负整数 numRows,生成杨辉三角的前 numRows 行 
 在杨辉三角中,每个数是它左上方和右上方的数的和。  示例:  输入: 5 输出: [      [1],     [1,1],    [1,2,1],   [1,3,3,1],  [1,4,6,4,1] ]
复制代码

 

复制代码
class Solution(object):     def generate(self, numRows):         """         :type numRows: int         :rtype: List[List[int]]         """                  #思路:除了第一行后其余每行都有两个1,因而将第一行单独列出来,第二行开始每行第一步添加1,然后开始计算上一行每两个数的求和,最后在进行添加1,         res=[]         if numRows==0:             return []         res.append([1])         for  i in range(1,numRows):             res.append([1])             for j in range(1,len(res[i-1])):                 res[i].append(res[i-1][j]+res[i-1][j-1])             res[i].append(1)         return res
复制代码

 

Python的每个对象都分为可变和不可变,主要的核心类型中,数字、字符串、元组是不可变的,列表、字典是可变的。  对不可变类型的变量重新赋值,实际上是重新创建一个不可变类型的对象,并将原来的变量重新指向新创建的对象(如果没有其他变量引用原有对象的话(即引用计数为0),原有对象就会被回收)。 可变对象:如果进行的是浅复制,那么存在任何一个对象修改,其他对象也会一起修改(地址相同) 不可变对象,如果进行的是浅复制,相当于深复制,地址不同
复制代码
print '可变' t=[1,3,4,1] t_copy=t t_copy.append(12) print t,t_copy,id(t),id(t_copy) m={'123':2,'sada':3} m_copy=m m['qq']=5 print m,m_copy,id(m),id(m_copy) print '不可变' k='232' k_copy=k k+='s' print k,k_copy,id(k),id(k_copy) d=10 d_copy=d d_copy+=1 print d,d_copy,id(d),id(d_copy)   输出结果:  可变 [1, 3, 4, 1, 12] [1, 3, 4, 1, 12] 140630062594024 140630062594024 {'qq': 5, 'sada': 3, '123': 2} {'qq': 5, 'sada': 3, '123': 2} 140630062705752 140630062705752 不可变 232s 232 140630062701904 140630062750056 10 11 94639729410192 94639729410168
复制代码

 

 

复制代码
list内置函数:  len(list): 列表元素个数  max(list): 列表元素最大值,但list不为空.为空报错  min(list): 列表元素最小值,但list不为空.为空报错
方法:  添加:    list.append(obj) : 在列表末尾添加新的对象    list_extend(seq):  在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)  (原地) (对于单个字符串,进行添加每个字符)    list.insert(index,obj):  将对象插入列表(原地),index超过实际长度,则添加末尾  删除:    
    list.remove(obj) :移除当前list,指定的元素,删除成功返回 None, 否则报错,(原地操作)(删除为第一个出现)      list.pop(): 根据index进行删除元素, 返回删除的元素,否则报错.(原地)      del list[index]: 删除元素,原地  查找:
    list.index(obj) :指定元素进行查找,返回其index,但不存在则报错(返回第一个出现的index)         list[index]: 指定索引进行查找,不存在报错  改:    直接对指定位置进行赋值即可  排序:    list.sort(cmp=None,key=None,reverse=False)

        cmp -- 可选参数, 如果指定了该参数会使用该参数的方法进行排序。

        key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。(主要用于元祖等,在list中存储的对象)

        reverse -- 排序规则,reverse = True 降序, reverse = False 升序(默认)。

  list.count(obj): 统计某个元素在列表中出现的次数
  list.reverse(): 对当前list进行翻转(原地)
复制代码
字符串  是一个不可变对象,内置函数和方法    http://www.runoob.com/python/python-strings.html
复制代码
 最长公共前缀 编写一个函数来查找字符串数组中的最长公共前缀。  如果不存在公共前缀,返回空字符串 ""。  示例 1:  输入: ["flower","flow","flight"] 输出: "fl" 示例 2:  输入: ["dog","racecar","car"] 输出: "" 解释: 输入不存在公共前缀。 说明:  所有输入只包含小写字母 a-z 。
复制代码
复制代码
class Solution(object):     def longestCommonPrefix(self, strs):         """         :type strs: List[str]         :rtype: str                           """ #         思路,每一次获取第一个元素的前几个字符,与其他元素的前几个字符进行比较,不相等,则返回上个长度的字符,         if strs==[]:             return ''         if len(strs)==1:             return strs[0]         for i in range(1,len(strs[0])+1):             current_str=strs[0][:i]             for j  in range(1,len(strs)):                 next_str=strs[j][:i]                 if next_str!=current_str:                     return strs[0][:i-1]                          return strs[0]
复制代码
复制代码
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回  -1。  示例 1:  输入: haystack = "hello", needle = "ll" 输出: 2 示例 2:  输入: haystack = "aaaaa", needle = "bba" 输出: -1
复制代码
复制代码
class Solution(object):     def strStr(self, haystack, needle):         """         :type haystack: str         :type needle: str         :rtype: int         """ #    思路:利用字符串中的index方法,进行寻找,不存在则通过try-except返回-1         if len(needle)==0:             return 0         try:             index_=haystack.index(needle)         except:             return -1         return index_
复制代码
复制代码
二进制求和 给定两个二进制字符串,返回他们的和(用二进制表示)。  输入为非空字符串且只包含数字 1 和 0。  示例 1:  输入: a = "11", b = "1" 输出: "100" 示例 2:  输入: a = "1010", b = "1011" 输出: "10101"
复制代码
复制代码
class Solution(object):     def addBinary(self, a, b):         """         :type a: str         :type b: str         :rtype: str         """ #         int的操作: int(t,base)  base :2为二进制, 默认为十进制   bin()  进行二进制计算 ,返回一二二进制,形如:'ob1010'         return bin(int(a,2)+int(b,2))[2:]
复制代码
复制代码
双指针技巧,它可以帮助我们解决许多与数组/字符串相关的问题https://leetcode-cn.com/explore/learn/card/array-and-string/201/two-pointer-technique/786/

总结


总之,使用双指针技巧的典型场景之一是你想要

从两端向中间迭代数组。

这时你可以使用双指针技巧:

一个指针从始端开始,而另一个指针从末端开始。

值得注意的是,这种技巧经常在排序数组中使用。

情景二:

这是你需要使用双指针技巧的一种非常常见的情况:

同时有一个慢指针和一个快指针。

解决这类问题的关键是

确定两个指针的移动策略。

与前一个场景类似,你有时可能需要在使用双指针技巧之前对数组进行排序,也可能需要运用贪心想法来决定你的运动策略。

复制代码
复制代码
反转字符串 编写一个函数,其作用是将输入的字符串反转过来。  示例 1:  输入: "hello" 输出: "olleh" 示例 2:  输入: "A man, a plan, a canal: Panama" 输出: "amanaP :lanac a ,nalp a ,nam A"
复制代码
复制代码
class Solution(object):     def reverseString(self, s):         """         :type s: str         :rtype: str         """         # return s[::-1]         # return (''.join(list(reversed(s))))                  #思路:利用双指针方法,定义左指针和右指针,依次交换元素,字符串是不可变,因为可以将其通过list转换为可变对象,然后在通过join进行连接,即可完成字符串的修改         left=0         s_list=list(s)         right=len(s_list)-1         while left<=right:             temp=s[left]             s_list[left]=s_list[right]             s_list[right]=temp             left+=1             right-=1         return ''.join(s_list)
复制代码
复制代码
两数之和 II - 输入有序数组 给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。  函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。  说明:  返回的下标值(index1 和 index2)不是从零开始的。 你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。 示例:  输入: numbers = [2, 7, 11, 15], target = 9 输出: [1,2] 解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。
复制代码
复制代码
class Solution(object):     def twoSum(self, numbers, target):         """         :type numbers: List[int]         :type target: int         :rtype: List[int]         """         n=len(numbers)         if n<2:             return []         left=0         right=n-1         while left<=right:             if numbers[left]+numbers[right]==target: #            答案是唯一的                 return [left+1,right+1]             elif numbers[left]+numbers[right]<target:                 left+=1             else:                 right-=1         return []
复制代码
情景2
复制代码
移除元素 给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。  不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。  元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。  示例 1:  给定 nums = [3,2,2,3], val = 3,  函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。  你不需要考虑数组中超出新长度后面的元素。 示例 2:  给定 nums = [0,1,2,2,3,0,4,2], val = 2,  函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。  注意这五个元素可为任意顺序。  你不需要考虑数组中超出新长度后面的元素。
复制代码
复制代码
class Solution:     def removeElement(self, nums, val):         """         :type nums: List[int]         :type val: int         :rtype: int         """         #定义双指针,使用了两个指针,i一个用于原始数组的迭代,k另一个总是指向新数组的最后一个位置         k=0         for i in range(len(nums)):             if nums[i]!=val:                 nums[k]=nums[i]                 k+=1         return k         
复制代码
复制代码
最大连续1的个数 给定一个二进制数组, 计算其中最大连续1的个数。  示例 1:  输入: [1,1,0,1,1,1] 输出: 3 解释: 开头的两位和最后的三位都是连续1,所以最大连续1的个数是 3. 注意:  输入的数组只包含 0 和1。 输入数组的长度是正整数,且不超过 10,000。
复制代码
复制代码
class Solution(object):     def findMaxConsecutiveOnes(self, nums):         """         :type nums: List[int]         :rtype: int         """         #定义双指针,一个记录其连续的次数,一个用于迭代         k=0         return_=0         for i in range(len(nums)):             if nums[i]==1:                 k+=1             else:                 return_=max(k,return_)                 k=0         return max(return_,k)
复制代码

 

复制代码
翻转字符串里的单词 给定一个字符串,逐个翻转字符串中的每个单词。  示例:    输入: "the sky is blue", 输出: "blue is sky the". 说明:  无空格字符构成一个单词。 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
复制代码
复制代码
class Solution(object):     def reverseWords(self, s):         """         :type s: str         :rtype: str         """         #思路:使用双指针,第一个指针记录不为' '的字符个数,第二个指针迭代         import re         list_s = re.split(' ', s)         prev=0         for i in range(len(list_s)):             if list_s[i] != '':                 list_s[prev]=list_s[i]                 prev+=1         del list_s[prev:]         list_s.reverse()         return ' '.join(list_s)
复制代码
复制代码
反转字符串中的单词 III 给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。  示例 1:  输入: "Let's take LeetCode contest" 输出: "s'teL ekat edoCteeL tsetnoc"  注意:在字符串中,每个单词由单个空格分隔,并且字符串中不会有任何额外的空格。
复制代码
复制代码
class Solution(object):     def reverseWords(self, s):         """         :type s: str         :rtype: str         """        #         list_s=s.split(' ')         for i in range(len(list_s)):            #下面两种形式都可以实现字符的翻转,但是不可用指针形式对字符进行赋值翻转,因为字符是不可变             # list_s[i]=''.join(reversed(list_s[i]))             list_s[i]=list_s[i][::-1]         return ' '.join(list_s)
复制代码
复制代码
删除排序数组中的重复项 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。  不要使用额外的数组空间,你必须在原地修改输入数组并在使用 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 removeDuplicates(self, nums):         """         :type nums: List[int]         :rtype: int         """ #         思路:使用双指针,一个记录不重复的元素,一个迭代         pre=0         for i in range(1,len(nums)):             if nums[i]!=nums[pre]:                 nums[pre+1]=nums[i]                 pre+=1         del nums[pre+1:]                 
复制代码
复制代码
移动零 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。  示例:  输入: [0,1,0,3,12] 输出: [1,3,12,0,0] 说明:  必须在原数组上操作,不能拷贝额外的数组。 尽量减少操作次数。
复制代码
复制代码
class Solution(object):     def moveZeroes(self, nums):         """         :type nums: List[int]         :rtype: void Do not return anything, modify nums in-place instead.         """ #    思路: 利用双指针,一个记录不为0的个数,一个迭代         pre=0         for i in range(len(nums)):             if nums[i]!=0:                 nums[pre]=nums[i]                 pre+=1         for k in range(pre,len(nums)):             nums[k]=0
复制代码

 数组练习题:

 

复制代码
643. 子数组最大平均数 I 给定 n 个整数,找出平均数最大且长度为 k 的连续子数组,并输出该最大平均数。 示例 1: 输入: [1,12,-5,-6,50,3], k = 4 输出: 12.75 解释: 最大平均数 (12-5-6+50)/4 = 51/4 = 12.75 注意: 1 <= k <= n <= 30,000。 所给数据范围 [-10,000,10,000]。https://leetcode-cn.com/problems/maximum-average-subarray-i/
复制代码
复制代码
class Solution(object):     def findMaxAverage(self, nums, k):         """         :type nums: List[int]         :type k: int         :rtype: float         """ #     思路:利用双指针,一前一后,前后差距为k         res_sum=sum_=sum(nums[:k])         left=0         right=k         while right<len(nums):             sum_-=nums[left]             sum_+=nums[right]             res_sum=max(sum_,res_sum)             left+=1             right+=1         return res_sum*1.0/k     
复制代码
复制代码
914:卡牌分组  给定一副牌,每张牌上都写着一个整数。 此时,你需要选定一个数字 X,使我们可以将整副牌按下述规则分成 1 组或更多组: 每组都有 X 张牌。 组内所有的牌上都写着相同的整数。 仅当你可选的 X >= 2 时返回 true。 示例 1:  输入:[1,2,3,4,4,3,2,1] 输出:true 解释:可行的分组是 [1,1],[2,2],[3,3],[4,4] 示例 2:  输入:[1,1,1,2,2,2,3,3] 输出:false 解释:没有满足要求的分组。 示例 3:  输入:[1] 输出:false 解释:没有满足要求的分组。 示例 4:  输入:[1,1] 输出:true 解释:可行的分组是 [1,1] 示例 5:  输入:[1,1,2,2,2,2] 输出:true 解释:可行的分组是 [1,1],[2,2],[2,2]  提示:  1 <= deck.length <= 10000 0 <= deck[i] < 10000 https://leetcode-cn.com/problems/x-of-a-kind-in-a-deck-of-cards/
复制代码
复制代码
class Solution(object):     def hasGroupsSizeX(self, deck):         """         :type deck: List[int]         :rtype: bool         """ #         思路:有题目可知,可通过dict求取每个元素 个数,并判断他们之间是否存在公约数(不为1),存在返回True,         if deck==[]:             return []         dict_={}         for i in deck:             if i not in dict_:                 dict_[i]=0             dict_[i]+=1         print dict_         num_min=min(dict_.values())         if num_min==1:             return False         for i in range(2,num_min+1):             flag=True             #对每个数字的次数进行对i求余,如果全部都为0,那么表明该全部元素之间存在公约数             for j in dict_:                 if dict_[j]%i!=0:                     flag=False             if flag==True:                 return True         return False          
复制代码

 

复制代码
941:有效的山脉数组 给定一个整数数组 A,如果它是有效的山脉数组就返回 true,否则返回 false。  让我们回顾一下,如果 A 满足下述条件,那么它是一个山脉数组:  A.length >= 3 在 0 < i < A.length - 1 条件下,存在 i 使得: A[0] < A[1] < ... A[i-1] < A[i] A[i] > A[i+1] > ... > A[B.length - 1]    示例 1:  输入:[2,1] 输出:false 示例 2:  输入:[3,5,5] 输出:false 示例 3:  输入:[0,3,2,1] 输出:true    提示:  0 <= A.length <= 10000 0 <= A[i] <= 10000  https://leetcode-cn.com/problems/valid-mountain-array/
复制代码
复制代码
class Solution(object):     def validMountainArray(self, A):         """         :type A: List[int]         :rtype: bool         """         #思路: 定义双指针,,双向遍历,前后元素满足条件则进行left  or  right 进行操作,         if len(A)<=2:             return False         left=0         right=len(A)-1         for i in range(len(A)-1):             if A[left+1]>A[left] :                 left+=1             if A[right]<A[right-1]:                 right-=1         if left!=right or right==len(A)-1 or left==0:             return False         return True
复制代码
复制代码
905:按奇偶排序数组 给定一个非负整数数组 A,返回一个由 A 的所有偶数元素组成的数组,后面跟 A 的所有奇数元素。  你可以返回满足此条件的任何数组作为答案。     示例:  输入:[3,1,2,4] 输出:[2,4,3,1] 输出 [4,2,3,1],[2,4,1,3] 和 [4,2,1,3] 也会被接受。    提示:  1 <= A.length <= 5000 0 <= A[i] <= 5000 https://leetcode-cn.com/problems/sort-array-by-parity/
复制代码
复制代码
class Solution(object):     def sortArrayByParity(self, A):         """         :type A: List[int]         :rtype: List[int]         """         odd=[]         even=[]         for i in A:             if i%2:                 odd.append(i)             else:                 even.append(i)         even.extend(odd)         return even
复制代码
复制代码
922: 按奇偶排序数据2 给定一个非负整数数组 A, A 中一半整数是奇数,一半整数是偶数。  对数组进行排序,以便当 A[i] 为奇数时,i 也是奇数;当 A[i] 为偶数时, i 也是偶数。  你可以返回任何满足上述条件的数组作为答案。     示例:  输入:[4,2,5,7] 输出:[4,5,2,7] 解释:[4,7,2,5],[2,5,4,7],[2,7,4,5] 也会被接受。    提示:  2 <= A.length <= 20000 A.length % 2 == 0 0 <= A[i] <= 1000  
复制代码
复制代码
class Solution(object):     def sortArrayByParityII(self, A):         """         :type A: List[int]         :rtype: List[int]         """         odd=[]         even=[]         res=[]         for i in A:             if i%2:                 odd.append(i)             else:                 even.append(i)         for i in range(len(A)/2):             res.append(even[i])             res.append(odd[i])         return res
复制代码
复制代码
830. 较大分组的位置 在一个由小写字母构成的字符串 S 中,包含由一些连续的相同字符所构成的分组。  例如,在字符串 S = "abbxxxxzyy" 中,就含有 "a", "bb", "xxxx", "z" 和 "yy" 这样的一些分组。  我们称所有包含大于或等于三个连续字符的分组为较大分组。找到每一个较大分组的起始和终止位置。  最终结果按照字典顺序输出。  示例 1:  输入: "abbxxxxzzy" 输出: [[3,6]] 解释: "xxxx" 是一个起始于 3 且终止于 6 的较大分组。 示例 2:  输入: "abc" 输出: [] 解释: "a","b" 和 "c" 均不是符合要求的较大分组。 示例 3:  输入: "abcdddeeeeaabbbcd" 输出: [[3,5],[6,9],[12,14]] 说明:  1 <= S.length <= 1000 https://leetcode-cn.com/problems/positions-of-large-groups/
复制代码
复制代码
class Solution(object):     def largeGroupPositions(self, S):         """         :type S: str         :rtype: List[List[int]]         """         if len(S)<=2:             return []         left=0         right=1         count=1         res=[]         #思路: 利用双指针,进行遍历,满足则count+1,不满足count-1,如果最后还满足,那么记性判断count是否大于等于3         while right<len(S):             if S[right]==S[left] and right!=len(S)-1:                 count+=1                 right+=1             elif S[right]!=S[left]:                 if count>=3:                     res.append([left,right-1])                 left=right                 right+=1                 count=1             elif S[right]==S[left] and right==len(S)-1:                 count+=1                 if count>=3:                     res.append([left,right])                 break         return res             
复制代码

 

复制代码
665. 非递减数列 给定一个长度为 n 的整数数组,你的任务是判断在最多改变 1 个元素的情况下,该数组能否变成一个非递减数列。  我们是这样定义一个非递减数列的: 对于数组中所有的 i (1 <= i < n),满足 array[i] <= array[i + 1]。  示例 1:  输入: [4,2,3] 输出: True 解释: 你可以通过把第一个4变成1来使得它成为一个非递减数列。 示例 2:  输入: [4,2,1] 输出: False 解释: 你不能在只改变一个元素的情况下将其变为非递减数列。 说明:  n 的范围为 [1, 10,000]。 https://leetcode-cn.com/problems/non-decreasing-array/
复制代码
复制代码
class Solution(object):     def checkPossibility(self, nums):         """         :type nums: List[int]         :rtype: bool         """ #    思路:通过简单的例子分析,会发现当第i个数字小于第i-1数字时,有两种替换方式,第一种是令第i个数字等于第i-1数字,另一种是第i-1数字等于第i数字.两种方式 的判别条件为i-2数字与第i个数字的比较,(也可以使用i-1与i+1进行比较,不过要注意范围)[1,3,1,2],[2,3,1,4]         flag=0         for i in range(1,len(nums)):             if nums[i]<nums[i-1]:                 flag+=1                 if flag>1:                     return False                 if i-2 < 0 or nums[i-2] <= nums[i]:                     nums[i-1] = nums[i]                 else:                     nums[i] = nums[i-1]         return True
复制代码
复制代码
628. 三个数的最大乘积 给定一个整型数组,在数组中找出由三个数组成的最大乘积,并输出这个乘积。  示例 1:  输入: [1,2,3] 输出: 6 示例 2:  输入: [1,2,3,4] 输出: 24 注意:  给定的整型数组长度范围是[3,104],数组中所有的元素范围是[-1000, 1000]。 输入的数组中任意三个数的乘积不会超出32位有符号整数的范围。 https://leetcode-cn.com/problems/maximum-product-of-three-numbers/
复制代码
复制代码
class Solution(object):     def maximumProduct(self, nums):         """         :type nums: List[int]         :rtype: int         """ #        思路:三个数的乘积最大,两种情况,第一种最大的三个数(大于0),第二种,最小的两个数(小于0)与最大的数         if len(nums)<3:             return 0         nums.sort()         return max(nums[0]*nums[1]*nums[-1],nums[-1]*nums[-2]*nums[-3])
复制代码
复制代码
896. 单调数列 如果数组是单调递增或单调递减的,那么它是单调的。  如果对于所有 i <= j,A[i] <= A[j],那么数组 A 是单调递增的。 如果对于所有 i <= j,A[i]> = A[j],那么数组 A 是单调递减的。  当给定的数组 A 是单调数组时返回 true,否则返回 false。     示例 1:  输入:[1,2,2,3] 输出:true 示例 2:  输入:[6,5,4,4] 输出:true 示例 3:  输入:[1,3,2] 输出:false 示例 4:  输入:[1,2,4,5] 输出:true 示例 5:  输入:[1,1,1] 输出:true https://leetcode-cn.com/problems/monotonic-array/
复制代码
复制代码
class Solution(object):     def isMonotonic(self, A):         """         :type A: List[int]         :rtype: bool         """         # 思路 :  对原数组进行复制,通过对原数组进行正向排序,相等返回True,不相等,有可能该原数组为逆序         if len(A)<=2:             return True         import copy         A_copy=copy.copy(A)         A.sort()         if A_copy==A:             return True         if A_copy[::-1]==A:             return True         return False
复制代码

 

复制代码
532. 数组中的K-diff数对 给定一个整数数组和一个整数 k, 你需要在数组里找到不同的 k-diff 数对。这里将 k-diff 数对定义为一个整数对 (i, j), 其中 i 和 j 都是数组中的数字,且两数之差的绝对值是 k.  示例 1:  输入: [3, 1, 4, 1, 5], k = 2 输出: 2 解释: 数组中有两个 2-diff 数对, (1, 3) 和 (3, 5)。 尽管数组中有两个1,但我们只应返回不同的数对的数量。 示例 2:  输入:[1, 2, 3, 4, 5], k = 1 输出: 4 解释: 数组中有四个 1-diff 数对, (1, 2), (2, 3), (3, 4) 和 (4, 5)。 示例 3:  输入: [1, 3, 1, 5, 4], k = 0 输出: 1 解释: 数组中只有一个 0-diff 数对,(1, 1)。 注意:  数对 (i, j) 和数对 (j, i) 被算作同一数对。 数组的长度不超过10,000。 所有输入的整数的范围在 [-1e7, 1e7]。
复制代码
复制代码
’‘’ 思路:         对原数组进行排序,然后通过双指针进行遍历,如果前后原数组在前后指针的数值相减的绝对值等于K,那么count+1,前后指针分别加1,如果大于k(表明前后指针的数组值相差过大,那么对后指针+1),否则快指针进行+1,         过程中:主要注意两个地方,1.数组对有可能存在重复,所以要对每一步生成的数组对进行记录,对重复的进行舍去。     2.后指针不能超过前指针 ,如果相等,那么对后指针进行+1处理。  ‘’‘ class Solution(object):     def findPairs(self, nums, k):         """         :type nums: List[int]         :type k: int         :rtype: int         """         nums.sort()         slow_index=0         fast_index=1         count_=0         set_=set()         while fast_index<len(nums):             if abs(nums[slow_index]-nums[fast_index])==k and nums[fast_index]+nums[slow_index] not in set_:                 set_.add(nums[fast_index]+nums[slow_index])                  slow_index+=1                 fast_index+=1                  count_+=1             elif abs(nums[slow_index]-nums[fast_index])>k:                 slow_index+=1             else:                 fast_index+=1             if slow_index==fast_index:                 fast_index+=1         return count_         
复制代码
复制代码
925. 长按键入  你的朋友正在使用键盘输入他的名字 name。偶尔,在键入字符 c 时,按键可能会被长按,而字符可能被输入 1 次或多次。  你将会检查键盘输入的字符 typed。如果它对应的可能是你的朋友的名字(其中一些字符可能被长按),那么就返回 True。     示例 1:  输入:name = "alex", typed = "aaleex" 输出:true 解释:'alex' 中的 'a' 和 'e' 被长按。 示例 2:  输入:name = "saeed", typed = "ssaaedd" 输出:false 解释:'e' 一定需要被键入两次,但在 typed 的输出中不是这样。 示例 3:  输入:name = "leelee", typed = "lleeelee" 输出:true 示例 4:  输入:name = "laiden", typed = "laiden" 输出:true 解释:长按名字中的字符并不是必要的。    提示:  name.length <= 1000 typed.length <= 1000 name 和 typed 的字符都是小写字母。
复制代码
复制代码
''' 思路:利用双指针分别遍历两个数组,对name的数组依次取出一个数,对typed数组进行遍历,如果遇到与name取出的元素相等,则推出,否则type_index+1   注意点:1.当name遍历到最后一个元素时,type是否还有元素进行遍历。   2. 避免name遍历时,type已经没有元素可以进行遍历 '''  class Solution(object):     def isLongPressedName(self, name, typed):         """         :type name: str         :type typed: str         :rtype: bool         """         name_index=0       #name的index         typed_index=0         while name_index<len(name):             char=name[name_index]             name_index+=1             if name_index==len(name) and typed_index==len(typed):   #1.避免name遍历最后一个元素时,type是否还有元素进行遍历。                 return False             #2.避免遍历时,type已经没有元素可以进行遍历             flat=False             while typed_index<len(typed):                 if char==typed[typed_index]:                     typed_index+=1                     flat=True                     break                 typed_index+=1             if not flat:                 return False         return True         
复制代码

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!