题意整理
- 牛妹有一条由n个珠子组成的项链,每个珠子都有自己的颜色。
- 现在牛妹要截取一段尽可能长的珠子,但是截下的这一段不能有相同颜色的珠子。
方法一(暴力统计)
1.解题思路
简要分析:由于项链总共有n颗珠子,我们可以枚举所有的起始位置,然后从每个起始位置开始,最多截取n个珠子,每一个起始位置(记为start)对应的终点位置最多为start+n,如果超过n就对n取余。固定起始位置之后,就开始截取,可以用一个set集合存储之前截取过的珠子,一旦遇到颜色重复的珠子,直接终止循环,此时的set容量即为当前起点对应的最大珠子数。
- 首先定义结果变量,用于记录最终结果。
- 以每一个位置为起始点,往后截取。如果不在set,说明可以截取;如果在,说明已经是最大长度,记录下来。
2.代码实现
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param n int整型 * @param a int整型一维数组 * @return int整型 */ public int solve (int n, int[] a) { //初始化结果变量 int res=0; //以每一个位置为起始点,往后截取 for(int start=0;start<n;start++){ Set<Integer> set=new HashSet<>(); //最多截取n个 for(int i=start;i<start+n;i++){ //如果不在set,说明可以截取 if(!set.contains(a[i%n])){ set.add(a[i%n]); } //如果在,直接终止循环 else{ break; } } //记录每个起点往后截取的最长一段珠子长度 res=Math.max(res,set.size()); } return res; } }
3.复杂度分析
- 时间复杂度:最坏情况下,两层循环体总共执行次,所以时间复杂度是。
- 空间复杂度:最坏情况下,需要额外n个大小为n的哈希表,所以空间复杂度是。
方法二(滑动窗口+哈希表)
1.解题思路
简要分析:仔细琢磨这一句话,牛妹不喜欢同一个颜色出现两次,如果把珠子比作字符串中的字符串,颜色相同看作遇到了相同的字符,那么只要把珠子数组延长一倍,问题就转化为在一个字符串中寻找最长不含重复字符的子字符串。
- 初始化map,用于记录之前颜色相同珠子所在位置的下一位。
- 如果当前位置对应颜色的珠子曾经出现在map,则将滑动窗口起点移动到之前记录位置的后一位。
- 每一轮循环,都统计最长的珠子长度。
动图展示:
2.代码实现
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param n int整型 * @param a int整型一维数组 * @return int整型 */ public int solve (int n, int[] a) { //初始化map Map<Integer,Integer> map=new HashMap<>(); //res记录最长的珠子长度,start记录珠子起点 int res=0,start=0; for(int i=0;i<2*n;i++){ //如果之前出现在map,则将滑动窗口起点移动到之前记录位置的后一位 if(map.containsKey(a[i%n])){ start=Math.max(start,map.get(a[i%n])); } map.put(a[i%n],i+1); //每次都统计最长的珠子长度 res=Math.max(res,i-start+1); } return res; } }
3.复杂度分析
- 时间复杂度:循环最多执行次,所以时间复杂度是。
- 空间复杂度:需要额外大小为n的哈希表,所以空间复杂度是。