无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
python解决:
1.穷举法:
穷举除所有的字串,放到一个新的列表中,求出最长的连续字串
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if len(set(s)) == len(s):
return len(s)
list1 = []
s1 = ""
for i in range(0,len(s)):
s1 += s[i]
for j in s[i+1::1]:
l2 = list(s1)
if j not in l2:
s1 += j
else:
break
list1.append(s1)
s1 = ""
max = 0
for k in list1:
if max <= len(k):
max = len(k)
return max
>>>时间复杂度0(n2)
2.哈希表
1.python使用字典 模拟哈希表:
2.遍历当前字符串: 使用方法 enumerate 方法, 把 i 和 遍历出的 item 组合成 一个字典
3.如果这个 item 的值没有在字典中出现过,那么把这个值添加到字典中 : { item : i } 的格式 , 如果item在字典中,那么返回 当前长度 , 用maxnum 来承接 .
4.下次遍历中比较maxnum 和之前maxnum的大小 , 返回最大值
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
n = len(s)
maxnum = 0
index = -1
dict1 = {}
for i, c in enumerate(s):
if c in dict1:
index = max(index, dict1[c])
maxnum = max(maxnum, i - index)
dict1[c] = i
return maxnum
java解决方案:
1.穷举: 略
2.哈希表:
思路同python , 使用 Hashmap 对象 , Hashmap 对象使用 put()方法插入元素,使用get(key) = value 方法访问:
class Solution {
public int lengthOfLongestSubstring(String s) {
HashMap<Object, Object> dict1 = new HashMap<>();
int n = s.length();
int maxnum = 0;
int index = -1;
for(int i=0 ;i<s.length();i++){
int key = s.charAt(i);
if(dict1.containsKey(key)){
index = Math.max(index, (Integer)dict1.get(key));
}
maxnum = Math.max(maxnum,i-index);
dict1.put(key,i);
}
return maxnum;
}
}
寻找两个正序数组的中位数
给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的中位数。
进阶:你能设计一个时间复杂度为 O(log (m+n)) 的算法解决此问题吗?
示例 1:
输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
示例 2:
输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5
示例 3:
输入:nums1 = [0,0], nums2 = [0,0]
输出:0.00000
示例 4:
输入:nums1 = [], nums2 = [1]
输出:1.00000
示例 5:
输入:nums1 = [2], nums2 = []
输出:2.00000
python解决:
1.简单的分支:
把列表1 append 到列表2 然后 对列表2 进行排序 , 然后通过列表的索引找到中位数
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
for i in nums1:
nums2.append(i)
nums2.sort()
if len(nums2) % 2 == 0:
mid = (nums2[len(nums2)//2-1] + nums2[len(nums2)//2])/2
else:
mid = nums2[len(nums2)//2 ]
return mid
-
动用二分查找解决( 转载自jimimmy00745 发布于 2020-01-21 二分搜索Python3)
思路
看到了O(log(m+n))和有序数列,不难想到使用「二分查找」来解决此题。
可是这道题有两个数列,给找中位数带来了不小的困难,「二分查找」的细节更是举步维艰。
别怕,可以使用@liweiwei1419大佬总结的「二分查找模板」来快速解决细节问题。
这个题解可以看作是官方题解的使用「二分查找模板」的改写。
代码
交换顺序
为了减少思考,我们先假定一个序列的长度总不大于第二个。
如果大于了,那么就交换一下。
这样子做的原因
一开始如果不交换 nums1 和 nums2 ,mid2 = half_len - mid1 可能会是负数。if len(nums1) > len(nums2): nums1, nums2 = nums2, nums1
记录两个序列的长度
len1, len2 = len(nums1), len(nums2)
记录二分查找的信息
怎么二分查找呢?
假设两个序列按顺序合并了,那么中间点的位置就在(len1 + len2 + 1) // 2
假定这个理想中位数为x
考虑一般情况下,第一个序列存在一个数,其左边都是小于x,右边都大于。
对第二个序列也是一样。
我们对这两个数在各自序列的位置分别称作mid1和mid2。
所以我们首先先对第一个序列二分查找。
记录左边界,右边界为第一个序列的左右边界。
而查找的中间就是左右边界的中间点。
对于mid2,便是(len1 + len2 + 1) // 2减去mid1left, right, half_len = 0, len1, (len1 + len2 + 1) // 2 mid1 = (left + right) // 2 mid2 = half_len - mid1
更新二分查找的条件
上面分析的看起来不错
可是没有触及怎么更新二分查找的条件
如何来更新呢?
不妨这样想,最理想的情况下,两个序列的mid1和mid2应该是一样的。
这时候mid1左侧和mid2左侧的数都应该比mid1和mid2对应的数小。
所以可以肯定,如果mid2左侧的数比mid1对应的数都大,那么第一行的中间太靠左了。
可以这么想,如果mid2左侧的数比mid1对应的都大,那不如第二行的数选小一点而第一行的数选大一点,这样两个数会更接近。
要把第一行的中间往右,即二分查找的更新left。
反之更新right。套用模板。
记得mid1不要越过上限!while left < right: if mid1 < len1 and nums2[mid2-1] > nums1[mid1]: left = mid1 + 1 else: right = mid1 mid1 = (left + right) // 2 mid2 = half_len - mid1
返回情况判断
这道题还困难在它的判断条件上
完成了这样的二分查找,我们找到了第一行的中间数和第二行的中间数
我们要返回哪个?还是返回它们的一半?
如果两个序列的长度和是奇数的话,那么就有一个唯一的中间的数
而是偶数的话,就是两个中间值平均数
我们假想两个序列合并并排序,那么就有这个中位数分成左右两块
我们需要一个左边的最大值和一个右边的最小值
如何找到左边的最大值呢?
通常情况下,我们已经找到了mid1和mid2,对比这两个数。
小的那个就是右边的最小值。
而对比mid1和mid2左边的数,大的那个就是左边的最大值。
为什么是这个逻辑呢?为什么左侧两个数的是左边的最大值,而本身就是右边的最小值呢?为什么不是它们本身两者分高低呢?(有点绕,体会一下)
这样想,因为我们从0到(m + n) // 2总共共有(m + n) // 2 + 1个数(因为下标0也是一个数),这是大于半数的。而减去这俩中位数后,剩下的就正好是一半的数量。这即左半部分。所以我们找的mid其本身应该划分到右边部分。这里可以多找几个测试样例测试几次。
对了,还有一些特殊情况没考虑,就是比如第一行特别小的情况下,那么左大就是二行的mid2偏左,而右小就是二行的mid2。
如果总数是奇数,那么输出左大,如果是偶数,输出左大和右小的平均数。if mid1 == 0: max_of_left = nums2[mid2-1] elif mid2 == 0: max_of_left = nums1[mid1-1] else: max_of_left = max(nums1[mid1-1], nums2[mid2-1]) if (len1 + len2) % 2 == 1: return max_of_left if mid1 == len1: min_of_right = nums2[mid2] elif mid2 == len2: min_of_right = nums1[mid1] else: min_of_right = min(nums1[mid1], nums2[mid2]) return (max_of_left + min_of_right) / 2
完整代码
class Solution: def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float: if len(nums1) > len(nums2): nums1, nums2 = nums2, nums1 len1, len2 = len(nums1), len(nums2) left, right, half_len = 0, len1, (len1 + len2 + 1) // 2 mid1 = (left + right) // 2 mid2 = half_len - mid1 while left < right: if mid1 < len1 and nums2[mid2-1] > nums1[mid1]: left = mid1 + 1 else: right = mid1 mid1 = (left + right) // 2 mid2 = half_len - mid1 if mid1 == 0: max_of_left = nums2[mid2-1] elif mid2 == 0: max_of_left = nums1[mid1-1] else: max_of_left = max(nums1[mid1-1], nums2[mid2-1]) if (len1 + len2) % 2 == 1: return max_of_left if mid1 == len1: min_of_right = nums2[mid2] elif mid2 == len2: min_of_right = nums1[mid1] else: min_of_right = min(nums1[mid1], nums2[mid2]) return (max_of_left + min_of_right) / 2
作者:qsctech-sange
链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/dong-yong-er-fen-cha-zhao-mo-ban-lai-qiao-miao-jie/
java解决
1.分支:
建立一个新数组,把两个数组遍历一遍添加进来,然后排序,然后查找:
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int [] midarr = new int[nums1.length+ nums2.length];
int i = 0;
double mid;
for(int item : nums1){
midarr[i] = item;
i++;
}
for(int item : nums2){
midarr[i] = item;
i++;
}
Arrays.sort(midarr);
if (midarr.length%2==0){
int index = midarr.length/2 ;
mid = (double) (midarr[index-1]+midarr[index])/2;
}else{
int index = midarr.length/2 ;
mid = midarr[index];
}
return mid;
}
}