942. 增减字符串匹配【简单题】【每日一题】
思路:【模拟】
由题意可知,要返回的数组长度为
n+1
且每一个元素的取值范围是[0,n]
,又 当前i位置字符I
对应 数组i
位置元素比它右侧位置小 ,当前i位置字符D
对应 数组i
位置元素比它右侧位置大。
我们可以理解为I
–> 递增 ;D
-->递减,我们设递增起始值left = 0
,递减起始值right = n
,那么从左到右依次遍历字符串,遇到I
就将对应位置 数组元素赋值为left
,并使left
自增1
,遇到D
就将对应位置 数组元素赋值为right
,并使right
自减1
,最后将数组最后的未赋值位置赋值为此时的left
或right
,都可以。
代码:
class Solution {
public int[] diStringMatch(String s) {
int n = s.length();
int[] ans = new int[n+1];
char[] chars = s.toCharArray();
int left = 0,right = n,i = 0;
for (char c : chars) {
if (c == 'I'){
ans[i++] = left++;
}else {
ans[i++] = right--;
}
}
ans[i] = right;
return ans;
}
}
剑指 Offer II 034. 外星语言是否排序【简单题】
思路:【模拟】
使用
int
类型数组dic
存储给定字母表顺序,然后以单词列表第1
个单词为标准单词,从第2
个单词开始依次判断待判断单词与标准单词是否满足字典序排序,是则将待判断单词更新为标准单词继续下一个单词的判断,不是则函数返回false
。
代码:
class Solution {
public boolean isAlienSorted(String[] words, String order) {
//使用 dic 记录字母表顺序
int[] dic = new int[26];
for (int i = 0; i < 26; i++) {
dic[order.charAt(i)-'a'] = i;
}
//锚定一个起始单词
String word = words[0];
//求出起始单词的长度和单词列表的长度
int len = word.length(),n = words.length;
//从起始单词的下一个开始,依次遍历单词列表
for (int i = 1; i < n; i++) {
//定义单词顺序是否正确的标志位 初始为false
boolean flag = false;
//以起始单词长度为标准
for (int j = 0; j < len; j++) {
//如果 j >= 待判断单词的长度 说明待判断单词已遍历完毕,而此时标准单词仍有字符尚未判断,这种情况说明待判断单词与标准单词是不符合字典序排序的,函数返回false
if (j >= words[i].length()){
return false;
}
//定义当前位置标准单词的字符 left 当前位置待判断单词的字符 right
char left = word.charAt(j),right = words[i].charAt(j);
//如果left = right 则继续判断下一个位置,否则
if (left != right){
//当left != right 是,left 的字典序只能比right小,否则直接返回false
if (dic[left-'a'] < dic[right-'a']){
//left的字典序比right小,那么这两个单词已经判断完毕,符合题意,将标志位flag置为true,退出判断循环
flag = true;
break;
}else {
return false;
}
}
}
//如果flag为true,说明当前待判断单词与标准单词的字典序排序是正确的,否则,说明遍历完了依然全部相等,即待判断单词与标准单词是相等的,此时甚至标准单词都不用更新,直接进行下一个单词的判断即可
if (flag){
//字典序排序正确时,将标准单词更新为待判断单词,然后判断下一个单词
word = words[i];
}
}
//单词列表只有一个单词时,不会走上述判断循环,函数直接返回true 当所有的循环都走完,依然没有返回false,说明单词列表是严格按字典序排序的,此时返回true
return true;
}
}
剑指 Offer II 035. 最小时间差【中等题】
思路:【排序+鸽巢原理】
首先通过鸽巢原理将数据量压缩;当数据量大于
1440
时,必然会有重复的时间,此时最小时间差必然是0
,直接返回0
。
然后将timePoints
排序,这样最小时间差必然出现在两个相邻的时间,或者首尾时间之间。
代码:
class Solution {
public int findMinDifference(List<String> timePoints) {
int timeSize = timePoints.size();
if (timeSize > 1440){//一天总共就1440分钟,如果timePoints中的数据超过1440,那么必然有至少两个时间是重复的,最小时间差必然是0,直接返回0
return 0;
}
//对timePoints进行排序,这样的话最小时间差必然出现在两个相邻时间中,或者首尾时间中
Collections.sort(timePoints);
int min = Integer.MAX_VALUE;
String pre = timePoints.get(0);
for (int i = 1; i < timeSize; i++) {
int minute = getMinutes(timePoints.get(i),pre);
min = Math.min(min,minute);//求相邻时间的时间差,并更新min
pre = timePoints.get(i);
}
min = Math.min(min,getMinutes(timePoints.get(0),pre)+1440);//求首尾时间的时间差,并更新min
return min;
}
public int getMinutes(String time1,String time2){
int m1 = ((time1.charAt(0)-'0')*10 + (time1.charAt(1)-'0')) * 60 + (time1.charAt(3)-'0') * 10 + (time1.charAt(4)-'0');
int m2 = ((time2.charAt(0)-'0')*10 + (time2.charAt(1)-'0')) * 60 + (time2.charAt(3)-'0') * 10 + (time2.charAt(4)-'0');
return m1-m2;
}
}