滑动窗口:

左右指针,右指针右移动扩展,满足条件之后,左指针收缩。

// 模板
for () {// 将新进来的右边的数据,计算进来// 更新数据// 判断窗口数据是否不满足要求了while (窗口数据不满要求 && left < arrSize) {// 移除left数据,更新窗口数据left++;    }// 此时的res是都满足条件的,计算resres = right - left + 1right++;
}

992 有k个不同整数的子数组

字典+mostk

[LeetCode] 992. Subarrays with K Different Integers 有K个不同整数的子数组 - Grandyang - 博客园

class Solution(object):def mostk(self,nums,k):res=0left=0right=0dict={}while left<=right and right<len(nums):if nums[right] not in dict:dict[nums[right]]=1else:dict[nums[right]]=dict[nums[right]]+1#如果dict长度大于k,移动左指针,删掉dict中左指针指向的元素while len(dict)>k:#如果value为1,直接删除;如果value大于1,减去1if dict[nums[left]]==1:del dict[nums[left]]else:dict[nums[left]]=dict[nums[left]]-1left=left+1res+=right-left+1right=right+1return resdef subarraysWithKDistinct(self, nums, k):""":type nums: List[int]:type k: int:rtype: int"""return self.mostk(nums,k)-self.mostk(nums,k-1)

159 最多有2个不同字符的子串

双指针+哈希表

[LeetCode] 159. Longest Substring with At Most Two Distinct Characters 最多有两个不同字符的最长子串 - Grandyang - 博客园

class Solution(object):def lengthOfLongestSubstringTwoDistinct(self, s):""":type s: str:rtype: int"""
#移动右指针,通过字典来判断,是否需要移动左指针res=0left=0right=0dict={}while left<=right and right<len(s):if s[right] not in dict:dict[s[right]]=1else:dict[s[right]]=dict[s[right]]+1#如果dict长度大于2,移动左指针,删掉dict中左指针指向的元素while len(dict)>2:#如果value为1,直接删除;如果value大于1,减去1if dict[s[left]]==1:del dict[s[left]]else:dict[s[left]]=dict[s[left]]-1left=left+1cur_res=right-left+1if cur_res>res:res=cur_resright=right+1return res

76. 最小覆盖子串

滑动窗口

力扣

from collections import defaultdictclass Solution:def minWindow(self, s: str, t: str) -> str:'''如果hs哈希表中包含ht哈希表中的所有字符,并且对应的个数都不小于ht哈希表中各个字符的个数,那么说明当前的窗口是可行的,可行中的长度最短的滑动窗口就是答案。'''if len(s)<len(t):return ""hs, ht = defaultdict(int), defaultdict(int)#初始化新加入key的value为0for char in t:ht[char] += 1res = "" left, right = 0, 0 #滑动窗口cnt = 0 #当前窗口中满足ht的字符个数while right<len(s):hs[s[right]] += 1if hs[s[right]] <= ht[s[right]]: #必须加入的元素cnt += 1 #遇到了一个新的字符先加进了hs,所以相等的情况cnt也+1while left<=right and hs[s[left]] > ht[s[left]]:#窗口内元素都符合,开始压缩窗口hs[s[left]] -= 1left += 1if cnt == len(t):if not res or right-left+1<len(res): #res为空或者遇到了更短的长度res = s[left:right+1]right += 1return res作者:lin-shen-shi-jian-lu-k
链接:https://leetcode-cn.com/problems/minimum-window-substring/solution/leetcode-76-zui-xiao-fu-gai-zi-chuan-cja-lmqz/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
class Solution:def minWindow(self, s: str, t: str) -> str:#哈希表计数from collections import Counterdic_t=Counter(t)dic_s=Counter()count=0res_size=len(s)+1res=''#左右指针遍历,右指针的元素加入哈希表left=0right=0while right<len(s):dic_s[s[right]]+=1#判断是否应该包含在t内if dic_s[s[right]]<=dic_t[s[right]]:count+=1#什么时候移动左指针while left<right and dic_s[s[left]]>dic_t[s[left]]:dic_s[s[left]]-=1left+=1#判断是否满足t的长度if count==len(t):cur_size=right-left+1if cur_size<res_size:res_size=cur_sizeres=s[left:right+1]right+=1return res

904 水果成篮

超时的滑窗

#双指针:移动右指针,发现不满足条件之后再收缩左指针
#左指针逐位置搜索,通过70/90个case。优化时应该考虑,从maps里判断收缩。
# leetcode submit region begin(Prohibit modification and deletion)
class Solution:def totalFruit(self, fruits):res=0left=0right=0while left<=right and right<len(fruits):maps={}maps[fruits[right]]=1while right+1<len(fruits):right+=1if fruits[right] in maps:maps[fruits[right]]+=1else:maps[fruits[right]] = 1if len(maps)>2:right=right-1breakcur = right - left + 1res = max(res, cur)left+=1right=leftreturn res
fruits = [0,1,2,2]
# fruits = [3,3,3,1,2,1,1,2,3,3,4]
res=Solution().totalFruit(fruits)
print(res)

不超时的滑窗

#右指针始终往右边移动。根据条件判断左指针是否收缩def totalFruit2(self, fruits):res=0left=0right=0maps={}while left<=right and right<len(fruits):if fruits[right] not in maps:maps[fruits[right]]=1else:maps[fruits[right]]+=1#判断是否已经不满足条件,若不满足条件,收缩leftwhile len(maps)>2 :maps[fruits[left]]-=1if maps[fruits[left]]==0:del maps[fruits[left]]left+=1#计算cur=right-left+1res = max(res, cur)right+=1return res

209. 长度最小的子数组

滑窗

class Solution:def minSubArrayLen(self, target: int, nums: List[int]) -> int:#滑窗,当sum大于target时收缩左窗口,当sum等于target时计算一次结果#注意是≥ targetleft = 0right = 0cur_sum = 0res = float("inf")while right < len(nums):cur_sum += nums[right]#当cur_sum大于target时收缩左窗口while cur_sum >= target:cur_res = right - left + 1res = min(cur_res,res)cur_sum -= nums[left]left += 1right += 1if res == float("inf"):return 0return res

862. 和至少为 K 的最短子数组

队列中要存index。下面是我第一次写的,bug比较多:

1是没有存index, 而是存的值。

2是没有把队首元素弹出。

3是前缀和写法错误,

presum[j]-presum[i]表示的是nums[j]到nums[i+1],presum[j]-presum[i-1]表示的才是nums[j]到nums[i]
class Solution:def shortestSubarray(self, nums: List[int], k: int) -> int:#单调递增队列+前缀和#前缀和数组presum = [0 for _ in range(len(nums)+1)]for i in range(1,len(nums)+1):presum[i] = presum[i-1] + nums[i-1]res = float("inf")deq = deque()for i in range(len(nums)+1):#维护单调递增性while deq and deq[-1] > presum[i]:deq.pop()#都弹出之后deq.append(presum[i])#计算targetif deq and deq[-1] - deq[0] >= k:cur_res = len(deq)-1res = min(res,cur_res)if res == float("inf"):return -1return res

滑窗不行,没有单调性

单调递增队列

class Solution:def shortestSubarray(self, nums, k):res = float("inf")# 1,2,3# 1,3,6#presum[j]-presum[i]表示的是nums[j]到nums[i+1],presum[j]-presum[i-1]表示的才是nums[j]到nums[i]#前缀和presum = [0 for _ in range(len(nums)+1)]for i in range(1,len(presum)):presum[i] = presum[i-1] + nums[i-1]#维护一个单调递增队列,队尾-队首>=k,说明找到了一个符合要求的答案from collections import dequedeq = deque()for i in range(len(presum)):#不满足单调性的话,弹出队尾while deq and presum[deq[-1]] > presum[i]:deq.pop()#满足单调递增性deq.append(i)#计算一次,注意这里要用while,比如nums = [17,85,93,-45,-21],k = 150,结果是85,93而不是17,85,93while presum[deq[-1]] - presum[deq[0]] >= k:cur_res = deq[-1] - deq.popleft()res = min(cur_res,res)if res == float("inf"):return -1return res

5977. 最少交换次数来组合所有的 1 II

class Solution {
public:int minSwaps(vector<int>& nums) {int n = nums.size();int cnt = accumulate(nums.begin(), nums.end(), 0);if(cnt == n || cnt == 0 || cnt == 1)return 0;int ans = 0;int temp = 0;for(int i = 0; i < cnt; i ++)if(nums[i] == 0)temp ++;ans = temp;for(int i = 0; i < n + cnt - 1; i ++)                                    //进行数组拼接{if(nums[(i + cnt) % n] == 0)                                         //如果新进的元素是0,则交换次数加1temp ++;                                                         //如果新出的元素是0,则交换次数减1if(nums[i % n] == 0)temp --;ans = min(ans, temp);}return ans;}
};作者:Luna_
链接:https://leetcode-cn.com/problems/minimum-swaps-to-group-all-1s-together-ii/solution/hua-dong-chuang-kou-shu-zu-pin-jie-by-lu-bed2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
class Solution:def minSwaps(self, nums: List[int]) -> int:n = len(nums)a = nums + numscnt1 = nums.count(1)res = float('inf')Window_len = cnt1cur = nums[ :Window_len].count(1)res = min(res, cnt1 - cur)for r in range(Window_len, n * 2):#--进rif a[r] == 1:cur += 1#--弹ll = r - Window_lenif a[l] == 1:cur -= 1#--更新resres = min(res, cnt1 - cur)return res作者:Hanxin_Hanxin
链接:https://leetcode-cn.com/problems/minimum-swaps-to-group-all-1s-together-ii/solution/cpython3javago-1hua-dong-chuang-kou-by-h-l4dl/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

环形数组特性

力扣

class Solution:def minSwaps(self, nums: List[int]) -> int:#窗口长度为1的个数,窗口里最少有几个0count1=0for i in range(len(nums)):if nums[i]==1:count1+=1count0=0for i in range(count1):if nums[i]==0:count0+=1min_count0=count0cur_index=count1while cur_index<len(nums)*2:pre_index=cur_index-count1if nums[pre_index%len(nums)]==0:count0-=1if nums[cur_index%len(nums)]==0:count0+=1min_count0=min(min_count0,count0)cur_index+=1return min_count0

1004. 最大连续1的个数 III

class Solution(object):def longestOnes(self, A, K):N = len(A)res = 0left, right = 0, 0zeros = 0 while right < N:if A[right] == 0:zeros += 1while zeros > K:if A[left] == 0:zeros -= 1left += 1res = max(res, right - left + 1)right += 1return res作者:fuxuemingzhu
链接:https://leetcode-cn.com/problems/max-consecutive-ones-iii/solution/fen-xiang-hua-dong-chuang-kou-mo-ban-mia-f76z/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    public int longestOnes(int[] A, int K) {int left = 0;//窗口左边的位置int maxWindow = 0;//窗口的最大值int zeroCount = 0;//窗口中0的个数for (int right = 0; right < A.length; right++) {if (A[right] == 0) {zeroCount++;}//如果窗口中0的个数超过了K,要缩小窗口的大小,直到0的个数//不大于K位置while (zeroCount > K) {if (A[left++] == 0)zeroCount--;}//记录最大的窗口maxWindow = Math.max(maxWindow, right - left + 1);}return maxWindow;}作者:sdwwld
链接:https://leetcode-cn.com/problems/max-consecutive-ones-iii/solution/hua-dong-chuang-kou-de-liang-chong-jie-j-8ses/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

1493. 删掉一个元素以后全为 1 的最长子数组

class Solution:def longestSubarray(self, nums: List[int]) -> int:left=0right=0count0=0res=0while right<len(nums):#当有2个0的时候,收缩左指针while count0>1:if nums[left]==0:count0-=1left+=1#right指针右边移动if nums[right]==0:count0+=1cur=right-1-left+1-1else:cur=right-left+1-1res=max(res,cur)right+=1return res

334 递增的三元子序列

题目要求时间复杂度o(n),空间复杂度o(1)

两种解法:

1.最长上升子序列问题,leetcode-最大最小问题-v2_MaYingColdPlay的博客-CSDN博客,这个时间复杂度是o(n^2),会超时。

2.双指针解法,满足时间复杂度要求。

# 双指针,一个min_val,一个middle_val,如果第三个比前两个大,返回true
class Solution(object):def increasingTriplet(self, nums):""":type nums: List[int]:rtype: bool"""min_val=float("inf")middle_val=float("inf")for val in nums:if val <= min_val:min_val = valelif val <= middle_val:middle_val = valelse:return True#说明当前值比min_val和middle_val都大return False

时间相关计算

539 最小时间差

class Solution(object):# 小时:分钟格式的数据。例如 22:13,22:14# 先按照小时排序,再按照分钟排序def convert(self,n1,n2):#2213,2314s1_hour=int(str(n1)[:2])s2_hour=int(str(n2)[:2])s1_minutes=int(str(n1)[2:])s2_minutes =int(str(n2)[2:])#如果第二个分钟小于第一个分钟,小时差减去1,分钟差是s2_minutes+60-s1_minutesif s2_minutes<s1_minutes:hour_diff=(s2_hour-s1_hour-1)*60minutes_diff=s2_minutes+60-s1_minutesres1 = hour_diff + minutes_diffelse:hour_diff = (s2_hour - s1_hour) * 60minutes_diff = s2_minutes - s1_minutesres1 = hour_diff + minutes_diffreturn min(res1,1440-res1)def getMinutes(self, timePoints):timePoints_merge=[]for i in range(len(timePoints)):cur=timePoints[i]hour=cur.split(":")[0]minutes=cur.split(":")[1]hour_minutes_str=hour+minutes# hour_minutes=int(hour_minutes_str)timePoints_merge.append(hour_minutes_str)timePoints_merge.sort()min_diff=self.convert(timePoints_merge[0],timePoints_merge[1])for i in range(1,len(timePoints_merge)):pre=timePoints_merge[i-1]cur=timePoints_merge[i]cur_diff=self.convert(pre,cur)min_diff=min(cur_diff,min_diff)#比较最后一个和第一个last_diff=self.convert(timePoints_merge[0],timePoints_merge[-1])min_diff = min(last_diff, min_diff)return min_diff
# timePoints=["23:59","00:00"]
# timePoints=["01:01","02:01","03:00"]
timePoints=["00:00","04:00","22:00"]
res=Solution().getMinutes(timePoints)
print(res)
def func(timePoints):timePoints.sort()left = -1right = 0min_time = 24*60n = len(timePoints)if n > 1440:return 0while right < len(timePoints):x = timePoints[left].split(":") # 数据y = timePoints[right].split(":")if int(y[1]) >= int(x[1]):time = (int(y[0]) - int(x[0]))*60 + (int(y[1]) - int(x[1]))else:time = (int(y[0]) - 1 - int(x[0]))*60 + int(y[1]) + 60 - int(x[1])if min(abs(time),1440-abs(time)) < min_time:min_time = min(abs(time),1440-abs(time))left = left + 1right = right + 1return min_time作者:lnnnnnnn
链接:https://leetcode-cn.com/problems/minimum-time-difference/solution/python3-pai-xu-by-lnnnnnnn-03qp/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

1185. 一周中的第几天

1911. 最大子序列交替和

记忆化递归,超时。用flag判断奇偶性就不超时。

class Solution:def maxAlternatingSum(self, nums: List[int]) -> int:cache={}#每个元素的下标选或者不选两种选择def dfs(index,child_index):if (index,child_index) in cache:return cache[(index,child_index)]if index==len(nums):return 0a,b,c=0,0,0#index不选a=dfs(index+1,child_index)#index选if child_index%2==0:b=dfs(index+1,child_index+1)+nums[index]else:c=dfs(index+1,child_index+1)-nums[index]cache[(index,child_index)]=max(a,b,c)return max(a,b,c)#真实index,在子序列里的indexreturn dfs(0,0)
class Solution:def maxAlternatingSum(self, nums: List[int]) -> int:cache={}#每个元素的下标选或者不选两种选择def dfs(index,flag):if (index,flag) in cache:return cache[(index,flag)]if index==len(nums):return 0a,b,c=0,0,0#index不选a=dfs(index+1,flag)#index选if flag:b=dfs(index+1,False)+nums[index]else:c=dfs(index+1,True)-nums[index]cache[(index,flag)]=max(a,b,c)return max(a,b,c)#真实index#flag代表奇数偶数,flag=True为偶数flag=Truereturn dfs(0,flag)

1567. 乘积为正数的最长子数组长度

滑窗+脑筋急转弯

class Solution:def getMaxLen(self, nums: List[int]) -> int:cnt, ans, firstMinus, lastMinus, minus = 0, 0, None, None, 0for i in range(len(nums) + 1):if i == len(nums) or nums[i] == 0:    #遍历完成或者为0时,清空计数,更新ansif minus % 2 == 0:   #如果负数为偶数个,就不用管了ans = max(ans, cnt)else:   #如果负数为奇数个,就去掉第一个或最后一个负数ans = max(ans, cnt - firstMinus, lastMinus)cnt, firstMinus, lastMinus, minus = 0, None, None, 0  #重新计数elif nums[i] > 0:  cnt += 1else:if firstMinus == None:    #记录下第一个和最后一个(此时最后一个就是第一个)firstMinus = cnt + 1lastMinus = cntelif lastMinus != None:   #出现了第二个负数,此时更新最后一个负数的位置lastMinus = cntminus += 1     #负数的个数cnt += 1return ans

1229 安排会议日程

遍历,超时

#找到2个人休息时间重合的部分,看是否满足duration要求
#以slots1为基准
def testv2(slots1,slots2,duration):slots1.sort()slots2.sort()for i in range(len(slots1)):cur_left=slots1[i][0]cur_right=slots1[i][1]for j in range(len(slots2)):#是否有交集if slots2[j][0]<cur_right and slots2[j][1]>cur_left:left_new=max(cur_left,slots2[j][0])right_new=min(cur_right,slots2[j][1])if right_new-left_new>=duration:return [left_new,left_new+duration]return []

双指针,不超时

class Solution:def minAvailableDuration(self, slots1: List[List[int]], slots2: List[List[int]], duration: int) -> List[int]:#------------双指针slots1.sort()slots2.sort()n1, n2 = len(slots1), len(slots2)i = 0j = 0 while i < n1 and j < n2:s1, e1 = slots1[i]s2, e2 = slots2[j]s = max(s1, s2)e = min(e1, e2)if e - s >= duration:return [s, s + duration]if e1 < e2:i += 1else:j += 1return []

1001. 网格照明

暴力,超时

class Solution:def gridIllumination(self, n: int, lamps: List[List[int]], queries: List[List[int]]) -> List[int]:# 暴力模拟# 暴力模拟def light_dark(x, y, label):gird[x][y] += label# 同一行同一列设置为1,叠加,关灯的时候减去1for j in range(n):gird[x][j] += labelgird[x][y] -= labelfor j in range(n):gird[j][y] += labelgird[x][y] -= label# 左对角线设置为1,左对角线上部分是(x-1,y-1),下部分是(x+1,y+1)/右对角线设置为1,右对角线上部分是(x-1,y+1),下部分是(x+1,y-1)for j in range(1, n):if x - j >= 0 and y - j >= 0:gird[x - j][y - j] += labelif x + j < n and y + j < n:gird[x + j][y + j] += labelif x - j >= 0 and y + j < n:gird[x - j][y + j] += labelif x + j < n and y - j >= 0:gird[x + j][y - j] += labeldef check_light(x, y):# 先检查上下左右有没有灯/上面一行,下面一行,自己的那行,到y+1for j in range(y - 1, y + 2):if [x - 1, j] in lamps and [x - 1, j] not in darked:light_dark(x - 1, j, -1)darked.append([x - 1, j])if [x, j] in lamps and [x, j] not in darked:light_dark(x, j, -1)darked.append([x, j])if [x + 1, j] in lamps and [x + 1, j] not in darked:light_dark(x + 1, j, -1)darked.append([x + 1, j])gird = [[0 for _ in range(n)] for _ in range(n)]visited = []for i in range(len(lamps)):if lamps[i] not in visited:row, col = lamps[i]light_dark(row, col, 1)visited.append(lamps[i])# 根据queries关灯res = []darked = []for i in range(len(queries)):row, col = queries[i]cur_ans = gird[row][col]# 如果是1,把四周设置为0if cur_ans > 0:check_light(row, col)res.append(1)else:res.append(cur_ans)return res

哈希表+数学

class Solution:def gridIllumination(self, n: int, lamps: List[List[int]], queries: List[List[int]]) -> List[int]:points = set()row, col, diagonal, antiDiagonal = Counter(), Counter(), Counter(), Counter()for r, c in lamps:if (r, c) in points:continuepoints.add((r, c))row[r] += 1col[c] += 1diagonal[r - c] += 1antiDiagonal[r + c] += 1ans = [0] * len(queries)for i, (r, c) in enumerate(queries):if row[r] or col[c] or diagonal[r - c] or antiDiagonal[r + c]:ans[i] = 1for x in range(r - 1, r + 2):for y in range(c - 1, c + 2):if x < 0 or y < 0 or x >= n or y >= n or (x, y) not in points:continuepoints.remove((x, y))row[x] -= 1col[y] -= 1diagonal[x - y] -= 1antiDiagonal[x + y] -= 1return ans作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/grid-illumination/solution/wang-ge-zhao-ming-by-leetcode-solution-7omu/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

6028. 统计道路上的碰撞次数

直接模拟 超时

class Solution(object):def countCollisions(self, directions):""":type directions: str:rtype: int"""# 遍历,当前是r,碰到l或者s停止,设置一个visited数组防止重复计算count = 0visited_index = set()directions=list(directions)left=0right=len(directions)for i in range(len(directions)):if directions[i] == 'R':# 往右for j in range(i + 1, len(directions)):if (i,j) in visited_index:breakif directions[j] == "L" :count += 2visited_index.add((i,j))directions[i] = "S"directions[j] = "S"breakif directions[j] == "S" :count += 1visited_index.add((i,j))directions[i] = "S"breakif directions[i] == 'L':# 往左for j in range(i - 1, -1, -1):if (j,i) in visited_index:break# if directions[j] == "L":#     breakif directions[j] == "R":count += 2visited_index.add((j,i))directions[i] = "S"directions[j] = "S"breakif directions[j] == "S":count += 1visited_index.add((j, i))directions[i] = "S"breakreturn count

分类讨论2次遍历

class Solution {public int countCollisions(String directions) {char[] dirs = directions.toCharArray();int n = dirs.length, cnt = 0;// 统计 L 操作出现的碰撞次数boolean leftLimit = false;for (int i = 0; i < n; i++) {// 左侧有车辆 S 或 R 时,说明左侧有界(L操作肯定会碰撞)if (!leftLimit && dirs[i] != 'L') leftLimit = true;if (dirs[i] == 'L' && leftLimit) cnt++;}// 统计 R 操作出现的碰撞次数boolean rightLimit = false;for (int i = n - 1; i >= 0; i--) {// 右侧有车辆 S 或 L 时,说明右侧有界(R操作肯定会碰撞)if (!rightLimit && dirs[i] != 'R') rightLimit = true;if (dirs[i] == 'R' && rightLimit) cnt++;}return cnt;}
}作者:smqk
链接:https://leetcode-cn.com/problems/count-collisions-on-a-road/solution/by-smqk-8530/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

954. 二倍数对数组

哈希表

力扣

class Solution:def canReorderDoubled(self, arr: List[int]) -> bool:num_map = collections.Counter(arr)for num in sorted(num_map, key=abs):if num_map[num] > num_map[2 * num]:return Falsenum_map[2 * num] -= num_map[num]return True作者:Jam007
链接:https://leetcode-cn.com/problems/array-of-doubled-pairs/solution/by-jam007-qk31/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

5302. 加密解密字符串

哈希表

哈希表真牛逼,当时我是用暴力的方法,解密的时候还用了个回溯,结果超时了,最后有2个例子通不过,那个回溯应该也没法剪枝。回溯是这样的

数组[['a', 'c'], ['b'], ['a', 'c'], ['d']],在每个index的子数组里选一个数,找出所有位置的不同组合,结果例如[a,b,c,d],index 1 上取a,index 2上取b,index3上取c,index4上取d

class Encrypter:def __init__(self, keys, values, dictionary):self.keys = keysself.values = valuesself.dictionary = dictionarydef encrypt(self, word1: str) -> str:res = ""for char in word1:index = self.keys.index(char)replace = self.values[index]res += replacereturn resdef decrypt(self, word2: str) -> int:# 间隔1count = 0all = []for i in range(0, len(word2), 2):cur_repalce=[]cur = word2[i:i + 2]#找出所有下标values_copy = self.values.copy()all_index = []while cur in values_copy:index = values_copy.index(cur)all_index.append(index)values_copy[index] = "-1"for j in range(len(all_index)):repalce = self.keys[all_index[j]]cur_repalce.append(repalce)all.append(cur_repalce)print(all)#回溯遍历所有组合情况,cur_repalce里可能有多个值path=[]dfs_res=[]def dfs(index):if index == len(all):dfs_res.append(path[:])returncur = all[index]for j in range(len(cur)):path.append(cur[j])dfs(index+1)path.pop()dfs(0)print(dfs_res)for i in range(len(dfs_res)):cur = "".join(dfs_res[i])if cur in self.dictionary:count += 1print(count)return count

哈希表解法如下。真的很简洁,万事总归先可以想想能不能用map

class Encrypter {
public:unordered_map<char, string> mp;unordered_map<string, int> dicts;Encrypter(vector<char>& keys, vector<string>& values, vector<string>& dictionary) {int n = keys.size();for (int i = 0; i < n; i++) { /* 保存映射关系 */mp[keys[i]] = values[i];}for (auto &d : dictionary) { /* 对dict加密, 计数 */dicts[encrypt(d)]++;}}string encrypt(string word1) { /* 加密 */string ans;for (auto &ch : word1) {ans += mp[ch];}return ans;}int decrypt(string word2) { /* 解密, 计数 */return dicts[word2];}
};作者:liu-xiang-3
链接:https://leetcode-cn.com/problems/encrypt-and-decrypt-strings/solution/c-mapshi-xian-by-liu-xiang-3-0930/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

467. 环绕字符串中唯一的子字符串

哈希表计数

leetcode-滑动窗口/双指针/哈希表相关推荐

  1. leetcode 滑动窗口1

    leetcode 滑动窗口1 leetcode159. 至多包含两个不同字符的最长子串 1. 题目 2. 解答 leetcode1151. 最少交换次数来组合所有的1 1. 题目 2. 解答 leet ...

  2. LeetCode练习五:哈希表

    文章目录 一.哈希表 1.1 哈希表简介 1.2 哈希函数 1.2.1 直接定址法 1.2.2 除留余数法 1.2.3 平方取中法 2.4 基数转换法 1.3 哈希冲突 1.3.1 开放地址法 1.3 ...

  3. 数据结构算法——滑动窗口问题(以LeetCode滑动窗口题为例)

    1. 滑动窗口 滑动窗口算法是在给定特定窗口大小的数组或字符串上执行要求的操作,它的原理与网络传输TCP协议中的滑动窗口协议(Sliding Window Protocol)基本一致. 这种技术可以将 ...

  4. LeetCode 滑动窗口(Sliding Window)类问题总结

    导语 滑动窗口类问题是面试当中的高频题,问题本身其实并不复杂,但是实现起来细节思考非常的多,想着想着可能因为变量变化,指针移动等等问题,导致程序反复删来改去,有思路,但是程序写不出是这类问题最大的障碍 ...

  5. leetcode 滑动窗口小结 (一)

    目录 小结以及代码框架 76. 最小覆盖子串 滑动窗口 代码以及注释 567. 字符串的排列 滑动窗口 438. 找到字符串中所有字母异位词 3. 无重复字符的最长子串 化简框架 reference ...

  6. 无重复字符最长字串的滑动窗口结合哈希表解法(注释详尽)

    这个解法是由leetcode上的jack这名用户上传,巧妙的使用了哈希表来缩短执行时间,非常值得学习,但是原作者并没有将原理和亮点讲的很清楚,所以我重新将它梳理了一遍发了出来. 思路: 这个解法是以常 ...

  7. 【代码随想录】【LeetCode】学习笔记04-哈希表

    前言 哈希法牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找. 如果遇到需要判断一个元素是否出现过的场景,应该第一时间想到哈希法! 四个常见哈希表类型对 ...

  8. leetcode 滑动窗口

    滑动窗口 文章目录 滑动窗口 模板框架 [76. 最小覆盖子串](https://leetcode-cn.com/problems/minimum-window-substring/) 思路分析 代码 ...

  9. leetcode 滑动窗口小结 (三)

    目录 978. 最长湍流子数组 题目 思路分析以及代码 1052. 爱生气的书店老板 题目 思考分析与初步代码 优化思路以及优化代码 1208. 尽可能使字符串相等 题目 思考分析以及代码 978. ...

最新文章

  1. 子类窗口向父类窗口传值
  2. python结果输出到excel-python实现数据导出到excel的示例--普通格式
  3. _DataStructure_C_Impl:SeqListBasedSort
  4. linux mate桌面主题下载_7款Linux桌面环境推荐,你值得拥有!
  5. 手误【删库】 == 跑路,不存在的 ——删瓦辛格
  6. 180°舵机的使用步骤
  7. 阿里科学家再获世界级荣誉,平头哥首席科学家谢源当选AAASFellow
  8. 熟悉HBase基本操作
  9. (转)Spring Boot (十五): Spring Boot + Jpa + Thymeleaf 增删改查示例
  10. Tomcat7出现HTTP Status 500 - java.lang.ClassCastException: org.apache.jasper.el.ELContextImpl cannot b
  11. 又一百度杰出科学家离职,百度研究院成中国AI的黄埔军校?
  12. u盾 签名pdf显示 “签名于修订版中删除”_Adobe Acrobat Reader DC for mac(免费pdf阅读)...
  13. Velocity 语法学习
  14. mysql select count() count(1)_select count()和select count(1)的区别和执行方式讲解
  15. lol云顶之奕助手_云顶之奕小小英雄介绍 除了棋子以外它也很重要!
  16. (个人简历一)用纯html写个人简历
  17. 分享美容护肤门店预约下单小程序开发制作功能介绍
  18. 计算机网络-什么是计算机网络?
  19. 网络带宽单位转换 — MB/s、Mb/s、Mbps、Mbit/s、Kbps
  20. Mybatis自定义轻量级分页组件(易集成,易拓展)

热门文章

  1. 修改web服务器默认端口号80,更改wordpress默认的80端口号
  2. JS fs async/sync
  3. 实现浏览器支持各种视频格式文件播放
  4. 拥有这五件冰箱好物,夏日幸福爆棚
  5. 表达谱(DGE)测序与转录组测序的差别
  6. Facebook三大黑料
  7. 为什么把牛奶倒入大海?
  8. html五子棋游戏原理讲解,纯JS实现五子棋游戏
  9. Sentinel下载哨兵数据(IDM或者迅雷下载)
  10. 明基逐鹿出席2016薪酬福利与激励创新论坛