2:移除元素
库函数的erase时间复杂度为O(n)
题目
1:移除元素
方法1:暴力法
public int removeElement(int[] nums, int val) {
//1:暴力法
int len = nums.length;
for(int i = 0; i < len;i++){
if(nums[i] == val){
for(int j = i+1; j < len; j++){
nums[j-1] = nums[j];
}
i--; // 注意:因为下标i以后的数值都向前移动了一位,所以i也向前移动一位,
len--;
}
}
return len;
}
这里需要注意的是:因为下标i以后的数值都向前移动了一位,所以i也向前移动一位。
方法2:
快慢指针法: 快指针用于查找新数组中的元素,慢指针用于指向新数组的下标
//for循环写法
class Solution {
public int removeElement(int[] nums, int val) {
//2:双指针法
int slow = 0;
for(int fast = 0;fast < nums.length; fast++){
if(nums[fast] != val){
nums[slow] = nums[fast];
slow++;
}
}
return slow;
}
}
//while循环写法
class Solution {
public int removeElement(int[] nums, int val) {
//2:双指针法
int slow = 0;
int fast = 0;
while(fast < nums.length){
if(nums[fast] != val){
nums[slow] = nums[fast];
slow++;
fast++;
}
else{
fast++;
}
}
return slow;
}
}
//这里slow不会+1是因为当slow+1的时候,slow指向的元素不一定是有效的
2:删除有序数组中的重复项
class Solution {
public int removeDuplicates(int[] nums) {
int slow = 0;
for(int fast = 1;fast < nums.length;fast++){
if(nums[fast] != nums[slow])
{
nums[slow+1] = nums[fast];
slow++;
}
}
return slow+1; //这里slow+1是因为新数组中至少会有一个元素,当slow+1的时候,slow指向的元素是有效的
}
}
//这里slow+1是因为新数组中至少会有一个元素,当slow+1的时候,slow指向的元素是有效的
3:移动零
class Solution {
public void moveZeroes(int[] nums) {
//双指针法将元素前移
int slow = 0;
for(int fast = 0;fast < nums.length;fast++){
if(nums[fast] != 0){
nums[slow] = nums[fast];
slow++;
}
}
//将后面的元素置0
for(; slow < nums.length;slow++){
nums[slow] = 0;
}
}
}
这道题后续还需要看看,暴力解法还有点问题
6月7日打卡完毕
4:比较含退格的字符串
思路:定义两个指针分别指向两个数组的尾部,并且定义backspaceS和backspaceT从后往前找,会遇到三种情况
情况1:当前指针S指向了#,则backspaceS++,S--。
情况2:当前指针S指向了字母,若则backspaceS>0,则backspaceS--,S--。
前两种情况是不能比较的,需要等两个数组全部获取到当前有效的字母,才能进行判断。
情况3:当前指针S指向了字母,若则backspaceS<=0,并且T指针指向的也是一个有效的字母,则开始判断,不相等就返回false,相等则继续判断(S--,T--)
class Solution {
public boolean backspaceCompare(String s, String t) {
int i = s.length() - 1;
int j = t.length() - 1;
int backspaceS = 0;
int backspaceT = 0;
while(i>=0 || j>=0){
while(i>=0){//处理字符串S
if(s.charAt(i) == '#'){ //如果当前字符为退格,则backspaceS+1,指针向前移动
backspaceS++;
i--;
}
else if(s.charAt(i) != '#' && backspaceS>0){//如果当前字符为字母且backspaceS>0,指针向前移动
backspaceS--;
i--;
}
else{//如果当前字符为字母且backspaceS<=0,则当前指针指向元素有效,退出循环,等待T数组
break;
}
}
while(j>=0){//处理字符串T
if(t.charAt(j) == '#'){ //如果当前字符为退格,则backspaceT+1,指针向前移动
backspaceT++;
j--;
}
else if(t.charAt(j) != '#' && backspaceT>0){//如果当前字符为字母且backspaceT>0,指针向前移动
backspaceT--;
j--;
}
else{//如果当前字符为字母且backspaceT<=0,则当前指针指向元素有效,退出循环,等待T数组
break;
}
}
//若不相等则返回
//这里有问题:不会进入第二个循环,但是会报第二个循环进行时候的越界错误,暂时不清楚原因
if(i>=0 && j>=0 && s.charAt(i) != t.charAt(j)){
return false;
}
//若两个string中有一个的指针已经走到头了,则返回fasle
if((i<0 && j >=0) || (i>=0 && j<0)){
return false;
}
i--;
j--;
}
return true;
}
}
总结:记一下这里的格式,即分别判断两个数组,while中嵌套两个while,但是时间复杂度仍是O(n).
这里还有一个问题:不会进入第二个循环,但是会报第二个循环进行时候的越界错误,暂时不清楚原因,需要加上i>=0 && j>=0才能解决问题。后续需要解决这个问题
5:有序数组的平方
见下一节