💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨
前言
本栏目将记录博主暑假从0开始刷力扣的算法题,每一条题目我都会把知识点抽丝剥茧地进行分析,以便大家更好的理解和学习,话不多说,肝!
序号 | 标题 | 力扣序号 |
1 | 移除元素 | 27 |
2 | 删除有序数组中的重复项 | 26 |
3 | 移动零 | 283 |
4 | 比较含退格的字符串 | 844 |
1.移除元素
题目:
给你一个数组 nums
和一个值 val
,你需要 原地 移除所有数值等于 val
的元素。元素的顺序可能发生改变。然后返回 nums
中与 val
不同的元素的数量。
假设 nums
中不等于 val
的元素数量为 k
,要通过此题,您需要执行以下操作:
- 更改
nums
数组,使nums
的前k
个元素包含不等于val
的元素。nums
的其余元素和nums
的大小并不重要。 - 返回
k
。
示例 :
输入:nums = [3,2,2,3], val = 3 输出:2, nums = [2,2,_,_] 解释:你的函数函数应该返回 k = 2, 并且 nums 中的前两个元素均为 2。 你在返回的 k 个元素之外留下了什么并不重要(因此它们并不计入评测)。
解题思路:双指针法(快慢指针法)
要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。
定义快慢指针
- 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
- 慢指针:指向更新 新数组下标的位置
代码(Java)
class Solution {
public int removeElement(int[] nums, int val) {
// 快慢指针
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < nums.length; fastIndex++) {
if (nums[fastIndex] != val) {
nums[slowIndex] = nums[fastIndex];
slowIndex++;
}
}
return slowIndex;
}
}
2.删除有序数组中的重复项
题目:
给你一个 非严格递增排列 的数组 nums
,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums
中唯一元素的个数。
考虑 nums
的唯一元素的数量为 k
,你需要做以下事情确保你的题解可以被通过:
- 更改数组
nums
,使nums
的前k
个元素包含唯一元素,并按照它们最初在nums
中出现的顺序排列。nums
的其余元素与nums
的大小不重要。 - 返回
k
。
示例 :
输入:nums = [1,1,2] 输出:2, nums = [1,2,_]
解题思路:
设置两个指针,一个在前记作 p,一个在后记作 q
如果相等,q 后移 1 位
如果不相等,将 q 位置的元素复制到 p+1 位置上,p 后移一位,q 后移 1 位
重复上述过程,直到 q 等于数组长度。
代码(Java)
class Solution {
public int removeDuplicates(int[] nums) {
if(nums == null || nums.length == 0) return 0;
int p = 0;
int q = 1;
while(q < nums.length){
if(nums[p] != nums[q]){
nums[p + 1] = nums[q];
p++;
}
q++;
}
return p + 1;
}
}
3.移动零
题目:
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 :
输入: nums =[0,1,0,3,12]
输出:[1,3,12,0,0]
解题思路:
两次遍历,采用双指针的思想,第一次把非0挪到前面,剩下的继续第二次遍历,把剩下的元素赋值为0
代码(Java)
class Solution {
public void moveZeroes(int[] nums) {
if(nums == null) {
return;
}
int j = 0;
for(int i = 0; i < nums.length; i++){
if(nums[i] != 0) {
nums[j++] = nums[i];
}
}
for(int i = j; i < nums.length; i++){
nums[i] = 0;
}
}
}
4.比较含退格的字符串
题目:
给定 s
和 t
两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true
。#
代表退格字符。(#就是删掉的意思)
注意:如果对空文本输入退格字符,文本继续为空。
示例 1:
输入:s = "ab#c", t = "ad#c" 输出:true 解释:s 和 t 都会变成 "ac"。
示例 2:
输入:s = "a#c", t = "b" 输出:false 解释:s 会变成 "c",但 t 仍然是 "b"。
思路解析:
由于 # 号只会消除左边的一个字符,所以对右边的字符无影响,所以我们选择从后往前遍历 S,T 字符串。
准备两个指针 i, j 分别指向 S,T 的末位字符,再准备两个变量 skipS,skipT 来分别存放 S,T 字符串中的 # 数量。
从后往前遍历 S,所遇情况有三,如下所示:
2.1 若当前字符是 #,则 skipS 自增 1;
2.2 若当前字符不是 #,且 skipS 不为 0,则 skipS 自减 1;
2.3 若当前字符不是 #,且 skipS 为 0,则代表当前字符不会被消除,我们可以用来和 T 中的当前字符作比较。
若对比过程出现 S, T 当前字符不匹配,则遍历结束,返回 false,若 S,T 都遍历结束,且都能一一匹配,则返回 true。
思路参考的作者:御三五 🥇
代码(Java)
class Solution {
public boolean backspaceCompare(String S, String T) {
int i = S.length() - 1, j = T.length() - 1; // 从两个字符串的末尾开始遍历
int skipS = 0, skipT = 0; // 分别记录S和T中需要跳过的字符数
while (i >= 0 || j >= 0) { // 当两个字符串中至少有一个还有未遍历的字符时继续
// 处理字符串S
while (i >= 0) {
if (S.charAt(i) == '#') { // 遇到退格字符
skipS++; // 需要跳过的字符数加1
i--; // 继续向前遍历
} else if (skipS > 0) { // 如果前面有退格字符需要跳过
skipS--; // 跳过当前字符
i--; // 继续向前遍历
} else {
break; // 没有退格字符需要跳过,跳出内层循环
}
}
// 处理字符串T,逻辑与S相同
while (j >= 0) {
if (T.charAt(j) == '#') {
skipT++;
j--;
} else if (skipT > 0) {
skipT--;
j--;
} else {
break;
}
}
// 比较两个字符串当前位置的字符
if (i >= 0 && j >= 0) { // 两个字符串当前位置都有字符
if (S.charAt(i) != T.charAt(j)) { // 如果字符不相等
return false; // 返回false
}
} else { // 如果只有一个字符串还有未遍历的字符
if (i >= 0 || j >= 0) { // 只要有一个字符串还有字符,就返回false
return false;
}
}
i--; // 继续向前遍历S
j--; // 继续向前遍历T
}
return true; // 两个字符串都遍历完毕,且对应位置的字符都相等,返回true
}
}
❤️❤️❤️小郑是普通学生水平,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄
💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍