LeetCode第220场周赛
1.重新格式化电话号码
题目描述:
样例:
解题思路:这道题目主要考察对字符串的处理,可以将字符串转化为字符数组,只保留号码数字,并统计号码的个数。第二步根据号码的个数进行处理,分为三种情况,第一种是当个数只剩下4个时,将这4个数字拆分成两组,结束任务;第二种是当个数只剩下2个时,将这两个数字加入到结果中,结束任务;第三种情况是除过前两种情况,每三个数字一组,直到将数字处理完。要避免出现只剩一个数字是一组或者有超过两组数字是两个的情况。
代码如下
:
class Solution {
public String reformatNumber(String number) {
char[] ch = number.toCharArray();
//String res = "";
int length = 0;
for(int i=0;i<number.length();i++){
if(number.charAt(i)!='-'&&number.charAt(i)!=' '){
//System.out.println(number.charAt(i));
ch[length] = number.charAt(i);
length++;
}
}
//System.out.println(length);
int l =length;
StringBuilder res = new StringBuilder();
int flag = 0;
while(length>0){
if(length==4){
if(flag!=0)
res.append("-");
res.append(ch[l-length]).append(ch[l+1-length]);
res.append("-");
res.append(ch[l+2-length]).append(ch[l+3-length]);
length-=4;
}else if(length==2){
if(flag!=0)
res.append("-");
res.append(ch[l-length]).append(ch[l+1-length]);
length-=2;
}else{
if(flag!=0)
res.append("-");
res.append(ch[l-length]).append(ch[l+1-length]).append(ch[l+2-length]);
length-=3;
flag=1;
}
}
return res.toString();
}
}
上面的代码在处理空字符和“-”时,处理的太过繁琐,可以用replace函数替换掉,比赛中忘记了这个简单的方法。
修改后如下:
class Solution {
public String reformatNumber(String number) {
number = number.replace(" ","");
number = number.replace("-","");
char[] ch = number.toCharArray();
int length = number.length();
int l =length;
StringBuilder res = new StringBuilder();
int flag = 0;
while(length>0){
if(length==4){
if(flag!=0)
res.append("-");
res.append(ch[l-length]).append(ch[l+1-length]);
res.append("-");
res.append(ch[l+2-length]).append(ch[l+3-length]);
length-=4;
}else if(length==2){
if(flag!=0)
res.append("-");
res.append(ch[l-length]).append(ch[l+1-length]);
length-=2;
}else{
if(flag!=0)
res.append("-");
res.append(ch[l-length]).append(ch[l+1-length]).append(ch[l+2-length]);
length-=3;
flag=1;
}
}
return res.toString();
}
}
2.删除子数组的最大得分
题目描述:
解题思路:就是求一个数组中,最大的不含重复元素的连续子序列之和。第一时间想到了双指针和Map,一个指针start记录此次不含重复元素的子序列开始元素的下标,另一个指针用来向后搜索。map用来记录当前子序列中出现过的元素,key是数组的值,value是数组值的下标。
首先将数组的第一个元素添加到map中,指针start指向下标0.
Map<Integer,Integer> map = new HashMap<>();
map.put(nums[0],0);
int start = 0;
接着开始遍历数组,分两种情况进行判断。第一种情况是判断当前数组元素是第一次出现或者是第一次出现在当前的子序列(划分一个子序列是看start的值,start为0,则当前子序列就是从下标0到当前下标;从i开始同理),则将元素添加到map,并计算序列和。第二种情况是当前子序列出现重复元素了,此时将start设置为子序列中重复元素第一次出现位置的后一位,并将此次子序列的和与之前最大的子序列和比较,接着计算当前元素的子序列和,并将元素添加到map中(相当于修改下标)。
代码如下:
class Solution {
public int maximumUniqueSubarray(int[] nums) {
Map<Integer,Integer> map = new HashMap<>();
int start = 0;
int []sum = new int[nums.length];
sum[0] = nums[0];
map.put(nums[0],0);
int res = 0;
for(int i=1;i<nums.length;i++){
if(!map.containsKey(nums[i]) || map.get(nums[i])<start){
map.put(nums[i],i);
sum[i] = sum[i-1] + nums[i];
}else{
res = Math.max(res,sum[i-1] - sum[start] + nums[start]);
start = map.get(nums[i]) + 1;
map.put(nums[i],i);
sum[i] = sum[i-1] + nums[i];
}
}
res = Math.max(res,sum[nums.length-1] - sum[start] +nums[start]);
return res;
}
}
3.跳跃游戏
题目描述:
解题思路:第一印象是贪心算法,但由于没有理解清题目的本质,导致在竞赛中没有按时完成,之后看了解析。本质分为两种情况,从当前元素可以跳到的位置,若是正数则每个都到达;若接下来所有可以达到的位置都是负数,只在这其中选择一个最大的即可。
代码如下:
class Solution {
public int maxResult(int[] nums, int k) {
int res = 0;
if(nums.length==1){
return nums[0];
}
for(int i=0;i<nums.length;){
res+=nums[i];
int index = i+1,max = Integer.MIN_VALUE;
for(int j=i+1;j<=i+k;j++){
if(j>=nums.length-1){
return res+nums[nums.length-1];
}
if(nums[j]>0){
index = j;
break;
}
if(nums[j]>max){
max = nums[j];
index = j;
}
}
i = index;
}
return res+nums[nums.length-1];
}
}
4.检查边长度限制的路径是否存在
题目描述:
样例: