[双指针]BM92 最长无重复子数组

一、题目

牛客题目链接最长无重复子数组_牛客题霸_牛客网

LeeCode 题目链接:

题目描述:

给定一个长度为n的数组arr,返回arr的最长无重复元素子数组的长度,无重复指的是所有数字都不相同。

子数组是连续的,比如[1,3,5,7,9]的子数组有[1,3],[3,5,7]等等,但是[1,3,7]不是子数组

数据范围:0≤arr.length≤10^{5},0<arr[i]≤10^{5}

示例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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值