题目大意:
删掉一个元素以后全为 1 的最长子数组
给你一个二进制数组 nums ,你需要从中删掉一个元素。
请你在删掉元素的结果数组中,返回最长的且只包含 1 的非空子数组的长度。
如果不存在这样的子数组,请返回 0 。
提示 1:
输入:nums = [1,1,0,1] 输出:3 解释:删掉位置 2 的数后,[1,1,1] 包含 3 个 1 。
示例 2:
输入:nums = [0,1,1,1,0,1,1,0,1] 输出:5 解释:删掉位置 4 的数字后,[0,1,1,1,1,1,0,1] 的最长全 1 子数组为 [1,1,1,1,1] 。
示例 3:
输入:nums = [1,1,1] 输出:2 解释:你必须要删除一个元素。
示例 4:
输入:nums = [1,1,0,0,1,1,1,0,1] 输出:4
示例 5:
输入:nums = [0,0,0] 输出:0
如果想查看本题目是哪家公司的面试题,请参考以下免费链接: https://leetcode.jp/problemdetail.php?id=1493
解题思路分析:
本题解法很多,这里提供2中思路。
解法一:dfs(递归)
我们从数组首元素开始向后dfs,dfs函数需要使用3个参数,分别为当前下标,是否使用过删除,当前连续长度。递归中,如果当前元素是1,那么我们将长度加一继续递归到下一位。如果当前元素是非1,我们可以将长度变为0,递归到下一位重新寻找最长区间。另外如果当前还未使用删除机会,那么我们可以忽略当前非1位,长度不变递归至下一位。每层递归中都需要使用当前长度更新全局最大长度。
另外,dfs递归中会存在重复路径,因此我们使用一个二维访问数组visited[][]记录已走过的点,避免重复计算。visited[i][j]代表下标为i并且当前删除次数剩余j的情况下是否已经递归过。
实现代码:
boolean[][] visited; // 访问数组 public int longestSubarray(int[] nums) { visited=new boolean[nums.length][2]; // 初始化访问数组 help(nums,0,1,0); // dfs递归 if(res==nums.length) res--; // 如果全是1,结果减一 return res; } int res=0; // 返回结果 // nums:数组 // index:当前下标 // delete:剩余删除次数 // 当前连续长度 void help(int[] nums, int index, int delete, int count){ res=Math.max(res,count); // 更新全局最大长度 if(index==nums.length) return; // 越界 if(visited[index][delete]) return; // 已访问过 visited[index][delete]=true; // 设置已访问过 if(nums[index]==1){ // 当前数为1 help(nums,index+1,delete,count+1); // 长度加一递归至下一位 }else{ // 当前数为非1 help(nums,index+1,1,0); // 将长度清零,递归至下一位重新统计 if(delete==1){ // 如果当前还未使用删除 help(nums,index+1,0,count); // 长度不变,递归至下一位 } } }
本题解法执行时间为18ms。
Runtime: 18 ms, faster than 8.46% of Java online submissions for Longest Subarray of 1’s After Deleting One Element.
Memory Usage: 58.9 MB, less than 50.00% of Java online submissions for Longest Subarray of 1’s After Deleting One Element.
解法二:
设置两个变量:
count1:当前包含一个非1的连续长度。 count2:当前全是1的连续长度。
循环数组每一个数字,如果当前数字是1,count1和count2同时加一,同时使用count1更新全局最大值。重点来了,如果当前数字是非1,则设count1等于count2,count2设为0。最后处理一下全是1的特例即可。
实现代码:
public int longestSubarray(int[] nums) { int count1=0; int count2=0; int res=0; for(int n : nums){ if(n==1){ count1++; count2++; res=Math.max(res,count1); }else{ count1=count2; count2=0; } } if(res==nums.length) res--; return res; }
本题解法执行时间为2ms。
Runtime: 2 ms, faster than 83.32% of Java online submissions for Longest Subarray of 1’s After Deleting One Element.
Memory Usage: 48.6 MB, less than 50.00% of Java online submissions for Longest Subarray of 1’s After Deleting One Element.
本网站文章均为原创内容,并可随意转载,但请标明本文链接如有任何疑问可在文章底部留言。为了防止恶意评论,本博客现已开启留言审核功能。但是博主会在后台第一时间看到您的留言,并会在第一时间对您的留言进行回复!欢迎交流!
本文链接: http://leetcode.jp/leetcode-1493-longest-subarray-of-1s-after-deleting-one-element-解题思路分析/