一、最短无序连续子数组
题意:
给你一个整数数组 nums
,你需要找出一个 连续子数组 ,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。请你找出符合题意的 最短 子数组,并输出它的长度。
输入:nums = [2,6,4,8,10,9,15] 输出:5 解释:你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序。
思路:
在 [2,6,4,8,10,9,15] 中,我们可以看出最后一个不符合升序的数字是9,第一个不符合升序的数字是6。其余两侧的元素都是正常的升序规律。
要点:所以我们这道题就是找左侧正常序列的结束点;右侧正常序列的起点。
右侧正常序列的起点:只要不出现右侧数字小于max;如果小于就要更新(此时更新的点就是起点)
for (int i = 1; i < nums.length; i++) {
if (max > nums[i])
endIndex = i;
max = Math.max(max, nums[i]);
}
左侧正常序列的结束点:主要不出现左侧数字大于min,如果大于就要更新(此时更新的点是结束点)
for (int i = nums.length-2; i >= 0; i--) {
if (min < nums[i])
startIndex = i;
min = Math.min(min, nums[i]);
}
代码:
/**
* 贪心算法:子数组中的最小值是大于数组的最小值的;最大值是小于数组的最大值的
*/
class Solution {
public int findUnsortedSubarray(int[] nums) {
if (nums == null || nums.length < 2) {
return 0;
}
int startIndex = nums.length-1;
int endIndex = 0;
int max = nums[0];
int min = nums[startIndex];
// max是这段范围中的最大值,要是在max的右边并且还比max小的 就要到数组里面进行排序
for (int i = 1; i < nums.length; i++) {
if (max > nums[i])
endIndex = i;
max = Math.max(max, nums[i]);
}
// min是这段范围中的最小值,要是在min的左边并且还比min大的 就要到min里面排序
for (int i = nums.length-2; i >= 0; i--) {
if (min < nums[i])
startIndex = i;
min = Math.min(min, nums[i]);
}
return startIndex - endIndex == nums.length - 1 ? 0 : endIndex - startIndex + 1;
}
}
二、长按键入
题意:
你的朋友正在使用键盘输入他的名字 name
。偶尔,在键入字符 c
时,按键可能会被长按,而字符可能被输入 1 次或多次。
你将会检查键盘输入的字符 typed
。如果它对应的可能是你的朋友的名字(其中一些字符可能被长按),那么就返回 True
。
给定一个name,每一个字符都有可能是多个的。判断typed缩减完是否是name。
思路:
left和right分别指向name和typed。
1.当name.charAt(left)==typed.charAt(right);两个指针同时向后移动;
2.当不相等的时候,要判断typed.charAt(right)==typed.charAt(right-1),
2.1如果相等的话就说明是长按的。
2.2如果不相等的话,就说明不匹配,直接return false;
代码:
class Solution {
public boolean isLongPressedName(String name, String typed) {
int left=0;
int right=0;
while(right<typed.length()){
if(left<name.length()&&name.charAt(left)==typed.charAt(right)){
left++;
}else if(right==0||typed.charAt(right)!=typed.charAt(right-1)){
return false;
}
right++;
}
return left==name.length();
}
}
三、移动片段得到字符
给你两个字符串 start
和 target
,长度均为 n
。每个字符串 仅 由字符 'L'
、'R'
和 '_'
组成,其中:其中片段 'L'
只有在其左侧直接存在一个 空位 时才能向 左 移动,而片段 'R'
只有在其右侧直接存在一个 空位 时才能向 右 移动。
思路:
‘L’左边有空格才能左移,‘R’右边有空格才能右移。
1.如果两个字符串去除'_'后不相同,那么就无法通过移动片段获得。
2.如果相同,那么顺序都是相同的;比较相同字符的下标。(如果'_'之后的字符都不相同 那么有直接return false)
2.1:如果碰到的是L,i<j; i无法左移得到j,直接返回false;
2.2:如果碰到的是R,i>j; i无法通过右移得到j,直接返回false;
3.如果有一个指针达到结尾了,直接break;
代码:
class Solution {
public boolean canChange(String start, String target) {
if(!start.replace("_","").equals(target.replace("_","")))return false;
int i=0;
int j=0;
while(i<start.length()&&j<target.length()){
while(i<start.length()&&start.charAt(i)=='_')i++;
while(j<target.length()&&target.charAt(j)=='_')j++;
//如果有一个提前到末尾 直接返回
if(i==start.length()||j==target.length())break;
//如果两个值都不相等 直接返回;
if(start.charAt(i)!=target.charAt(j))return false;
else{
if(start.charAt(i)=='L'&&i<j)return false;
if(start.charAt(i)=='R'&&i>j)return false;
}
i++;
j++;
}
return true;
}
}