一、题目
牛客题目链接:最长无重复子数组_牛客题霸_牛客网
LeeCode 题目链接:
题目描述:
给定一个长度为n的数组arr,返回arr的最长无重复元素子数组的长度,无重复指的是所有数字都不相同。
子数组是连续的,比如[1,3,5,7,9]的子数组有[1,3],[3,5,7]等等,但是[1,3,7]不是子数组
数据范围:0≤arr.length≤,0<arr[i]≤
示例1
输入:[2,3,4,5]
返回值:4
说明:[2,3,4,5]是最长子数组
示例2
输入:[2,2,3,4,3]
返回值:3
说明:[2,3,4]是最长子数组
示例3
输入:[9]
返回值:1
示例4
输入:[1,2,3,1,2,3,2,2]
返回值:3
说明:最长子数组为[1,2,3]
示例5
输入:[2,2,3,4,8,99,3]
返回值:5
说明:最长子数组为[2,3,4,8,99]
二、解题思路&代码实现
方案一:双指针+回头遍历
解题思路:
定义双指针, right指针对数组进行遍历,left指针对arr[right]前的子数组进行遍历。当left小于0或者遇到重复数字时,终止left遍历。
定义res代表最长的长度,tmp代表当前字符拥有的子串长度。
每次更新tmp时,也得更新res。
复杂度分析:
- 时间复杂度: O(n*n)
- 空间复杂度: O(1)
代码实现:
golang:
package main
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param arr int整型一维数组 the array
* @return int整型
*/
func maxLength(arr []int) int {
res := 0
tmp := 0
for right := 0; right < len(arr); right++ {
left := right - 1
//回头遍历
for left >= 0 && arr[right] != arr[left] {
left--
}
//若指针距离比上一个字符拥有的子串长度要大,就tmp+1 否则说明,遇到了重复数字,设置为新的指针距离,方便下一步res比较
if tmp < right-left {
tmp = tmp + 1
} else {
tmp = right - left
}
//更新res
res = Max(res, tmp)
}
return res
}
func Max(a, b int) int {
if a > b {
return a
}
return b
}
方案二:滑动窗口法
解题思路:
利用双指针模拟一个滑动窗口。初始化该窗口为(left, right]。所以left从-1开始。窗口不断往右扩大。因为我们要的是无重复子数组,因此,遇到有重复的数字,在窗口左侧进行缩小。
在每次滑动时,对窗口的大小进行比较,保留最大的长度。
复杂度分析:
- 时间: O(n) n为数组的长度
- 空间:O(n) n为HashMap的长度。
代码实现:
golang:
package main
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param arr int整型一维数组 the array
* @return int整型
*/
func maxLength(arr []int) int {
if len(arr) < 2 {
return len(arr)
}
// 使用 map 代替 Java 的 HashMap
window := make(map[int]int)
res := 0
left := -1 // 初始窗口左边界为 -1
for right := 0; right < len(arr); right++ {
// 如果当前元素已经出现在 map 中,并且位置 >= left,则更新 left
if pos, exists := window[arr[right]]; exists && pos > left {
left = pos
}
// 更新最大长度
if right-left > res {
res = right - left
}
// 将当前元素的位置记录进 map
window[arr[right]] = right
}
return res
}
php :
<?php
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param arr int整型一维数组 the array
* @return int整型
*/
function maxLength( $arr )
{
if (count($arr) < 2) {
return count($arr);
}
// 使用数组模拟 Java 的 HashMap
$window = [];
$res = 0;
$left = -1; // 窗口左边界初始为 -1
for ($right = 0; $right < count($arr); $right++) {
//如果当前元素在窗口中,并且位置 >= left
if (isset($window[$arr[$right]]) && $window[$arr[$right]] > $left) {
$left = $window[$arr[$right]]; // 更新左边界
}
// 计算当前窗口长度
$res = max($res, $right - $left);
// 记录当前元素的位置
$window[$arr[$right]] = $right;
}
return $res;
}