数组移除元素(快慢指针)
1.移除元素
暴力解法
class Solution {
/*
* 暴力解法:使用两层for循环,第一层循环遍历数组,第二层循环更新数组
*/
public int removeElement(int[] nums, int val) {
int len = nums.length;
for(int i =0;i<len;i++){
if(nums[i]==val){
for(int j =i+1;j<len;j++){
nums[i]=nums[j];//移除val,用i后面的元素覆盖
}
i--;//因为下表i以后的元素都向前移动一位,所以i也要向前移动一位
len--;//此时数组的大小减一
}
}
return len;
}
}
快慢指针
class Solution {
/*
* 快慢指针:慢指针用来存储修改后的元素,快指针用来遍历
*/
public int removeElement(int[] nums, int val) {
int slowIndex = 0;//慢指针,用来存储修改后的元素
for(int fastIndex = 0;fastIndex<nums.length;fastIndex++){//快指针用来遍历
if(val!=nums[fastIndex]){//如果当前值不等于目标值,则存储在慢指针下;若相等,则继续遍历,不存储。。
nums[slowIndex]=nums[fastIndex];
slowIndex++;
}
}
return slowIndex;
}
}
2.删除排序数组中的重复项
快慢指针删除数组中的元素,注意slowIndex++;和return slowIndex+1;
class Solution {
public int removeDuplicates(int[] nums) {
int slowIndex = 0;//用于存储修改后的元素
for(int fastIndex = 0;fastIndex<nums.length;fastIndex++){
if(nums[slowIndex]!=nums[fastIndex]){//不相等时才存储数据,两数相等就跳过
slowIndex++;//将数据存入慢指针下一位
nums[slowIndex]=nums[fastIndex];
}
}
return slowIndex+1;//slow从0开始,所以输出要加一
}
}
3.移动0
快慢指针,本题与前两道题的区别是,我们需要移动完元素后,在末尾加0
class Solution {
public void moveZeroes(int[] nums) {
int slowIndex =0;//慢指针,用来存储
for(int fastIndex =0;fastIndex<nums.length;fastIndex++){
if(nums[fastIndex]!=0){
nums[slowIndex]=nums[fastIndex];
slowIndex++;
}
}
//将后面的元素都变成0
for(int j =slowIndex;j<nums.length;j++){
nums[j]=0;
}
}
}
4.比较含退格的字符串
思路:我们选择从后向前遍历,定义sums和sumt来存储#的数量。
1.当前元素等于#时,sums/sumt加一
2.当前元素不等于#时,且sums/sumt大于0时,sums/sumt减一来抵消
3.当前元素不等于#时,且sums/sumt等于0时,退出当前循环
4.比较两个字符串是否相等
class Solution {
public boolean backspaceCompare(String s, String t) {
//双指针
int i = s.length()-1;//从后向前遍历
int j = t.length()-1;
int sums = 0;//用来记录s中#的数量
int sumt = 0;//用来记录t中#的数量
while(i>=0||j>=0){
//记录s中#的数量
while(i>=0){
if(s.charAt(i)=='#'){//当前元素等于#,记录下来
sums++;
i--;//可能为-1
}
else if(sums>0){//当前元素不等于#,且#的数量大于0
sums--;
i--;
}else{//当前元素不等于#,且#的数量等于0,退出循环去比较
break;//退出当前循环
}
}
//记录t中#的数量
while(j>=0){
if(t.charAt(j)=='#'){
sumt++;
j--;
}
else if(sumt>0){
sumt--;
j--;
}else{
break;
}
}
//比较除#外的元素是否相等
if(i>=0&&j>=0){
if(s.charAt(i)!=t.charAt(j)) return false;
}else{// (i >= 0 && j >= 0) 为 false 情况为
// 1. i < 0 && j >= 0
// 2. j < 0 && i >= 0
// 3. i < 0 && j < 0
// 其中,第 3 种情况为符合题意情况,因为这种情况下 s 和 t 都是 index = 0 的位置为 '#' 而这种情况下退格空字符即为空字符,也符合题意,应当返回 True。
// 但是,情况 1 和 2 不符合题意,因为 s 和 t 其中一个是在 index >= 0 处找到了待比较字 符,另一个没有找到
// 这种情况显然不符合题意,应当返回 False,下式便处理这种情况。
if(i>=0||j>=0){
return false;
}
}
i--;
j--;
}
return true;
}
}
5.有序数组的平方
各种排序的灵活使用
class Solution {
public int[] sortedSquares(int[] nums) {
for(int i =0;i<nums.length;i++){
nums[i]=nums[i]*nums[i];
}
return sort(nums);
}
//冒泡排序
private int[] sort(int[] nums){
for(int i =nums.length-1;i>0;i--){
for(int j =0;j<i;j++){//j+1,保证i后面必有一个
if(nums[j]>nums[j+1])
swap(nums,j,j+1);
}
}
return nums;
}
//两数交换
private void swap(int[] nums ,int i,int j){
int temp = nums[i];
nums[i]=nums[j];
nums[j]=temp;
}
}
平方在某种意义上也可以看作有序(首位两端)
注意要创建一个相同大小的数组进行数组的重新排序。(第一次忘记加了,然后就出错了)
class Solution {
/*
* 思路:有序数组的平方也可在某种意义上看作有序
*/
public int[] sortedSquares(int[] nums) {
int left = 0 ;
int right = nums.length-1;
int result[] = new int[right+1];//相同大小的新数组
int ans = nums.length-1;//新数组的指针
while(left<=right){
if(nums[left]*nums[left]<=nums[right]*nums[right]){
result[ans--]=nums[right]*nums[right];
right--;
}else{
result[ans--]=nums[left]*nums[left];
left++;
}
}
return result;
}
}