57 57. Insert Interval
思路 模拟
用指针去扫 intervals,最多可能有三个阶段:
- 不重叠的绿区间,在蓝区间的左边
- 有重叠的绿区间
- 不重叠的绿区间,在蓝区间的右边
逐个分析
不重叠,需满足:绿区间的右端,位于蓝区间的左端的左边,如 [1,2]。
则当前绿区间,推入 ans数组,指针 +1,考察下一个绿区间。
循环结束时,当前绿区间的屁股,就没落在蓝区间之前,有重叠了,如 [3,5]。
现在看重叠的。我们反过来想,没重叠,就要满足:绿区间的左端,落在蓝区间的屁股的后面,反之就有重叠:绿区间的左端 <= 蓝区间的右端,极端的例子就是 [8,10]。
和蓝有重叠的区间,会合并成一个区间:左端取蓝绿左端的较小者,右端取蓝绿右端的较大者,不断更新给蓝区间。
循环结束时,将蓝区间(它是合并后的新区间)推入 ans 数组。
剩下的,都在蓝区间右边,不重叠。不用额外判断,依次推入 ans 数组。
代码
class Solution {
public:
vector<vector<int>> insert(vector<vector<int>>& intervals, vector<int>& newInterval) {
vector<vector<int>> ans;
int i=0;
for (; i < intervals.size(); ++i) {
if (intervals[i][1]<newInterval[0]){
ans.push_back(intervals[i]);
}
else{
break;
}
}
int i_begin=i;
int end=newInterval[1];
if (i_begin>=intervals.size()){
intervals.push_back(newInterval);
return intervals;
}
int begin=min(intervals[i_begin][0],newInterval[0]);
while (i<intervals.size()&&intervals[i][1]<=newInterval[1]){
i++;
}
if (i>=intervals.size()){
ans.push_back({begin,newInterval[1]});
return ans;
}
if (intervals[i][0]<=newInterval[1])
{
end=intervals[i][1];
i++;
}
ans.push_back({begin,end});
for (; i < intervals.size(); ++i) {
ans.push_back(intervals[i]);
}
return ans;
}
};
764. Largest Plus Sign
思路
对数据进行缓存,缓存每一个坐标的当前列·行的长度信息至max_length_column
与max_length_row
。若对目标矩阵的每一个元素进行遍历,若缓存不存在则建立缓存,若缓存存在则直接返回缓存结果。最终的十字大小为min(列,行)
代码
class Solution {
private int n;
private int[][] mines_arr;
private int[][] max_length_column;
private int[][] max_length_row;
public int orderOfLargestPlusSign(int _n, int[][] mines) {
n = _n;
mines_arr = new int[n][n];
max_length_column = new int[n][n];
max_length_row = new int[n][n];
if (n * n == mines.length) {
return 0;
}
for (int[] vec : mines) {
mines_arr[vec[0]][vec[1]] = 1;
}
int curr_ans = 1;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (mines_arr[i][j] == 1) {
continue;
}
int column_length = max_length_column[i][j];
if (column_length == 0) {
updateColumn(i, j);
column_length = max_length_column[i][j];
}
int row_length = max_length_row[i][j];
if (row_length == 0) {
updateRow(i, j);
row_length = max_length_row[i][j];
}
curr_ans = Math.max(Math.min(column_length, row_length), curr_ans);
if (curr_ans == 3) {
int a = 3;
}
}
}
return curr_ans;
}
private void updateColumn(int r, int c) {
int r_org = r;
int curr = 1;
while (r < n && mines_arr[r][c] != 1) {
r++;
}
r--;
for (int i = r_org; i <= r; i++, r--) {
max_length_column[i][c] = curr;
max_length_column[r][c] = curr;
curr++;
}
}
private void updateRow(int r, int c) {
int column_org = c;
int curr = 1;
while (c < n && mines_arr[r][c] != 1) {
c++;
}
c--;
for (int i = column_org; i <= c; i++, c--) {
max_length_row[r][i] = curr;
max_length_row[r][c] = curr;
curr++;
}
}
}
766. Toeplitz Matrix
思路
模拟题,按照顺序遍历即可
代码
bool isToeplitzMatrix(vector<vector<int>> &matrix) {
int column_length=matrix[0].size();
int row_length=matrix.size();
int r = 0;
int c = 0;
while (c < column_length) {
int first_element=matrix[0][c];
for (int i = 1; i < min(column_length-c,row_length); ++i) {
if (matrix[i][c+i]!=first_element){
return false;
}
}
c++;
}
while (r < row_length) {
int first_element=matrix[r][0];
for (int i = 1; i < min(row_length-r,column_length); ++i) {
if (matrix[r+i][i]!=first_element){
return false;
}
}
r++;
}
return true;
}
796. Rotate String
思路(相对顺序不变)
首先应考虑原字符串和目标字符串长度相同。
考虑旋转后相对顺序不变的特点,在字符串后添加一个相同的原字符串,直接在修改后的字符串寻找是否存在目标字串即可。
bool rotateString(string _s, string goal) {
if (_s.length()!=goal.length()){
return false;
}
string s = _s + _s;
if (s.find(goal) != string::npos) {
return true;
}
return false;
}
816. Ambiguous Coordinates
思路 模拟
从坐标1开始尝试对每一个位置进行左右切分,并确认切分后的字串有多少种合法形式,然后令左右字串的合法形式做叉集即可。
代码
class Solution {
List<String> ans=new ArrayList<>();
public List<String> ambiguousCoordinates(String s) {
s=s.substring(1,s.length()-1);
for (int i=1;i<s.length();i++){
combineResults(s,i);
}
return ans;
}
public void combineResults(String str,int idx){
String[] x_axis=getValidateStrs(str.substring(0,idx));
String[] y_axis=getValidateStrs(str.substring(idx));
for (var x:x_axis){
for (var y:y_axis){
ans.add("("+x+", "+y+")");
}
}
}
public String[] getValidateStrs(String str){
ArrayList<String> res=new ArrayList<>();
char[] ch_list=str.toCharArray();
for (int i=1;i<ch_list.length;i++){
String integer_part=String.valueOf(ch_list,0,i);
if (integer_part.matches("^0.+")){
continue;
}
String decimal_part= str.substring(i);
if (decimal_part.endsWith("0")){
continue;
};
res.add(integer_part+"."+decimal_part);
}
if (!str.matches("^0.+")){
res.add(str);
}
return res.toArray(new String[0]);
}
}
937. Reorder Data in Log Files
思路 模拟
按照题目要求,首先对数字类和字母类的log进行分类,数组类的直接并入ArrayList、字母类的宪先并入,最后按照要求排序即可。要注意的是,处理字母类时最好存储为ArrayList<String[]> 方便排序。
代码
class Solution {
public String[] reorderLogFiles(String[] logs) {
ArrayList<String[]>alphaSet=new ArrayList<>();
ArrayList<String>numSet=new ArrayList<>();
for (String log:logs){
if (judgeNum(log)){
numSet.add(log);
continue;
}
alphaSet.add(log.split(" "));
alphaSet.sort((o1,o2)->{
int curr=1;
for (; curr < Math.min(o1.length,o2.length); curr++) {
int cmp=o1[curr].compareTo(o2[curr]);
if (cmp!=0){
return cmp;
}
}
if (o1.length==o2.length){
return o1[0].compareTo(o2[0]);
}
if (o1.length<o2.length){
return -1;
}
return 1;
});
}
String[] ans=new String[logs.length];
ArrayList<String> res= alphaSet.stream().map(obj->
String.join(" ",obj)
).collect(Collectors.toCollection(ArrayList::new));
for (int i = 0; i < res.size(); i++) {
ans[i]=res.get(i);
}
for (int i = 0; i < numSet.size(); i++) {
ans[i+res.size()]=numSet.get(i);
}
return ans;
}
boolean judgeNum(String string){
var list=string.split(" ",2);
return Character.isDigit(list[1].charAt(0));
}
}
1267. Count Servers that Communicate
思路
统计每一行列计算机的数量,然后再对grid的每一个元素进行遍历,若grid[i][j]为计算机且其所在行列数量大于1则结果+1;
代码
public int countServers(int[][] grid) {
int[] rowServers=new int[grid.length];
int[] columnServers=new int[grid[0].length];
int ans=0;
for (int i = 0; i < rowServers.length; i++) {
int rowSum=0;
for (int j = 0; j < columnServers.length; j++) {
rowSum+=grid[i][j];
}
rowServers[i]=rowSum;
}
for (int j = 0; j < columnServers.length; j++) {
int columnSum=0;
for (int i = 0; i <rowServers.length ; i++) {
columnSum+=grid[i][j];
}
columnServers[j]=columnSum;
}
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j <grid[0].length ; j++) {
if (grid[i][j]==1&&(rowServers[i]>1||columnServers[j]>1)){
ans++;
}
}
}
return ans;
}
1921. Eliminate Maximum Number of Monsters
思路 模拟
使用
d
i
s
t
i
/
s
p
e
e
d
i
dist_i/speed_i
disti/speedi即可求出每个怪物的到达时间
t
i
m
e
i
time_i
timei。对time
进行排序。只要任意时刻来的怪兽数量大于时间即返回结果,若没有则说明可以全部消灭。
代码
public int eliminateMaximum(int[] dist, int[] speed) {
double[] time=new double[dist.length];
for (int i = 0; i < dist.length; i++) {
time[i]=(double) dist[i]/speed[i];
}
Arrays.sort(time);
for (int i=0;i<dist.length;i++){
if (time[i]-i<=EPSILON){
return i;
}
}
return dist.length;
}
2240. Number of Ways to Buy Pens and Pencils
思路 模拟
对于每一个可能的cost1商品的数量(total-cnt_1*cost1>=0),计算cost2的商品一共有几种可能方案,求和即可。
代码
public long waysToBuyPensPencils(int total, int cost1, int cost2) {
long ans=0;
long cnt_1=0;
while (total-cnt_1*cost1>=0){
long residual=total-cnt_1*cost1;
ans+=residual/cost2+1;
cnt_1++;
}
return ans;
}
2840. Check if Strings Can be Made Equal With Operations II
思路
题目提到:
可以对两个字符串中的 任意一个 执行以下操作 任意 次:
选择两个下标 i 和 j ,满足 i < j 且 j - i 是 偶数,然后 交换 这个字符串中两个下标对应的字符。
也就是说 奇数位置和奇数位置之间的字符的位置可以任意互换,偶数位置和偶数位置之间的字符可以任意互换,因为他们满足j-i是偶数这一条件。因此,直接分别统计技术位和偶数位的各个字符的出现次数并比较两字符串的出现次数是否相同即可。
代码
class Solution {
public boolean checkStrings(String s1, String s2) {
int[] singleCnt=new int[26];
int[] evenCnt=new int[26];
for (int i=0;i<s1.length();i+=2){
singleCnt[s1.charAt(i)-'a']++;
}
for (int i=1;i<s1.length();i+=2){
evenCnt[s1.charAt(i)-'a']++;
}
for (int i=0;i<s2.length();i+=2){
singleCnt[s2.charAt(i)-'a']--;
if (singleCnt[s2.charAt(i)-'a']<0){
return false;
}
}
for (int i=1;i<s2.length();i+=2){
evenCnt[s2.charAt(i)-'a']--;
if (evenCnt[s2.charAt(i)-'a']<0){
return false;
}
}
return true;
}
}