leetcode-explore-learn-数据结构-数组5-小结
- 1.概述
- 2.例题
- 2.1旋转数组
- 2.2 杨辉三角2
- 2.3翻转字符串里的单词
- 2.4反转字符串中的单词3
- 2.5 删除排序数组中的重复项
- 2.6 移动零
本系列博文为leetcode-explore-learn子栏目学习笔记,如有不详之处,请参考leetcode官网:https://leetcode-cn.com/explore/learn/card/array-and-string/198/introduction-to-array/768/
所有例题的编程语言为python
1.概述
1.数组的常用排序算法及其时间复杂度分析十分重要
2.二分查找是一种十分重要的技术,用于在排序数组中搜索特i定元素
3.灵活应用双指针技巧十分重要,双指针技可以应用于:链表中快慢指针问题,滑动窗口问题
2.例题
2.1旋转数组
给定一个数组,将数组中的元素向右移动K个位置,其中k为非负数。
空间复杂度:o(1)
思路1:三次求逆:先整体求逆,然后nums[0,k]求逆,然后再nums[k+1:]求逆
class Solution(object):def rotate(self, nums, k):""":type nums: List[int]:type k: int:rtype: None Do not return anything, modify nums in-place instead."""def rever_nums(nums,l,r): # 原地置换,用index操作,nums[:flag]只是一个备份,没有修改元数组while(l<r):nums[l],nums[r]=nums[r],nums[l]l+=1r-=1n=len(nums)flag=k%nrever_nums(nums,0,n-1)rever_nums(nums,0,flag-1)rever_nums(nums,flag,n-1)return nums
思路2:计算每个数组移动到的目标位置,将目标位置的信息记录下来作为下一个操作的对象(30/35)—[-1,-100,3,99]2测试用例没过.
class Solution(object):def rotate(self, nums, k):""":type nums: List[int]:type k: int:rtype: None Do not return anything, modify nums in-place instead."""n=len(nums)action=0index=0current_val=nums[0]while(action<=n):target_index=(index+k)%ntarget_val=nums[target_index]nums[target_index]=current_valaction+=1index=target_indexcurrent_val=target_valreturn nums
修正思路:环装替换法
参考官网解题思路:https://leetcode-cn.com/problems/rotate-array/solution/xuan-zhuan-shu-zu-by-leetcode/
思路3,暴力法,每次移动一个,移动k次
(34/35)时间超出限制
class Solution(object):def rotate(self, nums, k):""":type nums: List[int]:type k: int:rtype: None Do not return anything, modify nums in-place instead."""n=len(nums)flag=k%nfor i in range(flag):current=nums[n-1]for j in range(n): # j:[0,n-1]temp=nums[j]nums[j]=currentcurrent=tempreturn nums
2.2 杨辉三角2
返回杨辉三角的第k行,算法空间复杂度,o(k)
思路1:计算整个杨辉三角,返回最后一行
class Solution(object):def getRow(self, rowIndex):res=[]for i in range(rowIndex+1): # i:[0,rowIndex] rowIndex+1行if i==0:res.append([1])elif i==1:res.append([1,1])else:res.append([1]*(i+1))for j in range(1,i):res[i][j]=res[i-1][j-1]+res[i-1][j]return res[-1]
思路2:空间复杂度优化,只有上一行计算下一行:
class Solution(object):def getRow(self, rowIndex):if rowIndex==0:return [1]if rowIndex==1:return [1,1]pre=[1,1]for i in range(2,rowIndex+1):cur=[1]*(i+1)for j in range(1,i):cur[j]=pre[j-1]+pre[j]pre=curreturn cur
2.3翻转字符串里的单词
给定一个字符串,逐个翻转字符串中的每个单词
**思路1:**要识别字符串中的每个单词,然后调整顺序。从最后开始遍历,识别一个单词后,往结果中添加。
class Solution(object):def reverseWords(self, s):""":type s: str:rtype: str"""res =""n=len(s)flag=0 # 判断是否开始识别一个单词for i in range(n-1,-1,-1):#print(i,s[i],flag)if s[i]!=" " and flag==0: # 一个单词的起始flag=1right=il_word=1elif s[i]!=" " and flag==1: # 单词左下标往前走l_word+=1elif s[i]==" " and flag==1: # 单词左下标走到了边界word=s[right-l_word+1:right+1]flag=0res+=wordres+=" "elif s[i]==" " and flag==0: # 多个空格的时候continueif flag==1: #最后还需要判断是否还有一个单词word=s[right-l_word+1:right+1]flag=0res+=wordlen_res=len(res)if len_res==0:return ""if res[-1]==" ":res=res[0:-1]return res
思路2:借助内置的函数
split() 将字符串按空格分成字符串数组
reverse() 将字符串数组翻转
join 将字符串数组拼接鞥一个字符串。
class Solution(object):def reverseWords(self, s):""":type s: str:rtype: str"""s_arr=s.split()s_arr.reverse()res=" ".join(s_arr)return res
2.4反转字符串中的单词3
给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。
思路:识别一个单词,送去翻转,添加至结果后
class Solution(object):def reverseWords(self, s):""":type s: str:rtype: str"""def rever_word(word):n=len(word)re_word=""for i in range(n-1,-1,-1):re_word+=word[i]#print(re_word)return re_wordn=len(s)l,r=0,0res=""while(r<n):if s[r]!=" ":r+=1elif s[r]==" ":word=s[l:r]res+=rever_word(word)res+=" "l=r+1r+=1word=s[l:r+1]res+=rever_word(word)return res
2.5 删除排序数组中的重复项
给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
**思路:**快慢指针:慢指针用于指示下一个写数字的位置,快指针用于遍历数组。每次判断快指针指向的数字在数组是否重复出现,如果重复出现就下一个,如果不是重复出现就更新慢指针的数值。
class Solution(object):def removeDuplicates(self, nums):""":type nums: List[int]:rtype: int"""n=len(nums)l=0target="INF"for r in range(n):if nums[r]!=target:target=nums[r]nums[l]=nums[r]l+=1 #指示下一个可以写的位置return l
2.6 移动零
给定一个数组,编写程序,完成将所有的零移动至数组的末尾,其他元素相对位置不变。
要求:原地操作,尽量少的操作次数
暴力求解思路:每次移动一个0.时间复杂度o(n^2)
class Solution(object):def moveZeroes(self, nums):""":type nums: List[int]:rtype: None Do not return anything, modify nums in-place instead."""n=len(nums)i=0j=n-1while(i<n and i<j): # print(i,j,nums)if nums[i]==0: # 置换完i不是立即+1,换完nums[i]处还可能是1for k in range(i,j):nums[k],nums[k+1]=nums[k+1],nums[k]j-=1else:i+=1 return nums
思路2双指针技巧:慢指针之前的元素都是非零,快指针与慢指针之间的元素都是0
class Solution(object):def moveZeroes(self, nums):""":type nums: List[int]:rtype: None Do not return anything, modify nums in-place instead."""n=len(nums)i,j=0,0while(i<n):if nums[i]:nums[i],nums[j]=nums[j],nums[i]j+=1i+=1