27.移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。
假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作:
- 更改
nums数组,使nums的前k个元素包含不等于val的元素。nums的其余元素和nums的大小并不重要。 - 返回
k。
用户评测:
评测机将使用以下代码测试您的解决方案:
int[] nums = [...]; // 输入数组
int val = ...; // 要移除的值
int[] expectedNums = [...]; // 长度正确的预期答案。
// 它以不等于 val 的值排序。
int k = removeElement(nums, val); // 调用你的实现
assert k == expectedNums.length;
sort(nums, 0, k); // 排序 nums 的前 k 个元素
for (int i = 0; i < actualLength; i++) {
assert nums[i] == expectedNums[i];
}
如果所有的断言都通过,你的解决方案将会 通过。
示例 1:
输入:nums = [3,2,2,3], val = 3 输出:2, nums = [2,2,_,_] 解释:你的函数函数应该返回 k = 2, 并且 nums 中的前两个元素均为 2。 你在返回的 k 个元素之外留下了什么并不重要(因此它们并不计入评测)。
示例 2:
输入:nums = [0,1,2,2,3,0,4,2], val = 2 输出:5, nums = [0,1,4,0,3,_,_,_] 解释:你的函数应该返回 k = 5,并且 nums 中的前五个元素为 0,0,1,3,4。 注意这五个元素可以任意顺序返回。 你在返回的 k 个元素之外留下了什么并不重要(因此它们并不计入评测)。
提示:
0 <= nums.length <= 1000 <= nums[i] <= 500 <= val <= 100
暴力法
时间复杂度:O(n^2) 空间复杂度:O(1)
class Solution {
public int removeElement(int[] nums, int val) {
int l = nums.length;
for(int i = 0;i<l;i++){//i小于更新后的数组长度
if(nums[i]==val){
for(int j = i+1;j<l;j++){//j小于更新后的数组长度
nums[j-1]=nums[j];
}
l--;//删除元素后更新数组长度
i--;//删除元素后,剩下元素的下标提前,i减1
}
}
return l;
}
}
双指针法(快慢指针法)
通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
时间复杂度:O(n) 空间复杂度:O(1)
class Solution {
public int removeElement(int[] nums, int val) {
int fast = 0;//快指针用来记录非value的元素
int slow = 0;//慢指针用来更新数组
for(fast = 0;fast<nums.length;fast++){
if(nums[fast]!=val){//快指针指向非val的元素时,更新数组,元素下标为slow
nums[slow]=nums[fast];
slow++;
}
}
return slow;
}
}
26.删除有序数组中的重复项
给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。
考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:
- 更改数组
nums,使nums的前k个元素包含唯一元素,并按照它们最初在nums中出现的顺序排列。nums的其余元素与nums的大小不重要。 - 返回
k。
判题标准:
系统会用下面的代码来测试你的题解:
int[] nums = [...]; // 输入数组
int[] expectedNums = [...]; // 长度正确的期望答案
int k = removeDuplicates(nums); // 调用
assert k == expectedNums.length;
for (int i = 0; i < k; i++) {
assert nums[i] == expectedNums[i];
}
如果所有断言都通过,那么您的题解将被 通过。
示例 1:
输入:nums = [1,1,2] 输出:2, nums = [1,2,_] 解释:函数应该返回新的长度2,并且原数组 nums 的前两个元素被修改为1,2。不需要考虑数组中超出新长度后面的元素。
示例 2:
输入:nums = [0,0,1,1,1,2,2,3,3,4] 输出:5, nums = [0,1,2,3,4] 解释:函数应该返回新的长度5, 并且原数组 nums 的前五个元素被修改为0,1,2,3,4。不需要考虑数组中超出新长度后面的元素。
提示:
1 <= nums.length <= 3 * 104-104 <= nums[i] <= 104nums已按 非严格递增 排列
class Solution {
public int removeDuplicates(int[] nums) {
int fast = 1;//nums[0]第一个元素不需要修改,从下标1开始
int slow = 1;
for(fast = 1;fast<nums.length;fast++){
if(nums[fast-1]!=nums[fast]){
nums[slow]=nums[fast];
slow++;
}
}
return slow;
}
}
283.移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 1:
输入: nums =[0,1,0,3,12]输出:[1,3,12,0,0]
示例 2:
输入: nums =[0]输出:[0]
提示:
1 <= nums.length <= 104-231 <= nums[i] <= 231 - 1
class Solution {
public void moveZeroes(int[] nums) {
int fast = 0;
int slow = 0;
for(fast = 0;fast<nums.length;fast++){
if(nums[fast]!=0){
nums[slow] = nums[fast];
slow++;
}
}
while(slow<nums.length){
nums[slow]=0;
slow++;
}
}
}
844.比较含退格的字符串
给定 s 和 t 两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true 。# 代表退格字符。
注意:如果对空文本输入退格字符,文本继续为空。
示例 1:
输入:s = "ab#c", t = "ad#c" 输出:true 解释:s 和 t 都会变成 "ac"。
示例 2:
输入:s = "ab##", t = "c#d#" 输出:true 解释:s 和 t 都会变成 ""。
示例 3:
输入:s = "a#c", t = "b" 输出:false 解释:s 会变成 "c",但 t 仍然是 "b"。
提示:
1 <= s.length, t.length <= 200s和t只含有小写字母以及字符'#'
进阶:
- 你可以用
O(n)的时间复杂度和O(1)的空间复杂度解决该问题吗?
1.求出两个退格后的字符串,再比较,空间复杂度较大
class Solution {
public static String changeS(String s) {
StringBuilder ss = new StringBuilder(s);
int skipS=0;
int slow = s.length()-1;
for(int fast = ss.length()-1;fast>=0;fast--) {
if(ss.charAt(fast)=='#') {
skipS++;
}else {
if(skipS==0) {
ss.setCharAt(slow, ss.charAt(fast));
slow--;
}else if(skipS != 0) {
skipS--;
}
}
}
while(slow>=0) {
ss.setCharAt(slow--, ' ');
}
return ss.toString().trim();
}
public static String changeT(String t) {
StringBuilder tt = new StringBuilder(t);
int skipT=0;
int slow = t.length()-1;
for(int fast = tt.length()-1;fast>=0;fast--) {
if(tt.charAt(fast)=='#') {
skipT++;
}else {
if(skipT==0) {
tt.setCharAt(slow, tt.charAt(fast));
slow--;
}else if(skipT != 0) {
skipT--;
}
}
}
while(slow>=0) {
tt.setCharAt(slow--, ' ');
}
return tt.toString().trim();
}
public boolean backspaceCompare(String s, String t) {
return changeS(s).equals(changeT(t));
}
}
2.从右往左遍历,找到两个字符串未删除的字符,字符间作比较,空间复杂度低
class Solution {
public boolean backspaceCompare(String s, String t) {
int i = s.length()-1;//从字符串右边开始遍历
int j = t.length()-1;
int skipS = 0;
int skipT = 0;
while(i>=0||j>=0) {
while(i>=0) {//找到字符串s不需要删除的字符位置
if(s.charAt(i)=='#') {
skipS++;
i--;
}else{
if(skipS>0) {
skipS--;
i--;
}
else if(skipS==0) {
break;
}
}
}
while(j>=0) {//找到字符串t不需要删除的字符位置
if(t.charAt(j)=='#') {
skipT++;
j--;
}else{
if(skipT>0) {
skipT--;
j--;
}
else if(skipT==0) {
break;
}
}
}
if(i>=0&&j>=0) {//如果字符串为空,或者左边都是‘#’,下标会变成-1,导致超出下标范围
if(s.charAt(i)!=t.charAt(j)) {//比较两个字符,不相等返回false
return false;
}
}
i--;
j--;
}
if(i==j) {//如果两个字符串为空,或者前面都是‘#’,最后i,j也相等
return true;
}else {//字符长度不同
return false;
}
}
}
977.有序数组的平方
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1:
输入:nums = [-4,-1,0,3,10] 输出:[0,1,9,16,100] 解释:平方后,数组变为 [16,1,0,9,100] 排序后,数组变为 [0,1,9,16,100]
示例 2:
输入:nums = [-7,-3,2,3,11] 输出:[4,9,9,49,121]
提示:
1 <= nums.length <= 104-104 <= nums[i] <= 104nums已按 非递减顺序 排序
进阶:
- 请你设计时间复杂度为
O(n)的算法解决本问题
class Solution {
public int[] sortedSquares(int[] nums) {
int front = 0;
int rear = nums.length-1;
int[] ans = new int[nums.length];//新开一个数组记录答案
int p = nums.length-1;//从尾部从大到小记录
while(front<=rear){
//也可以写成:-nums[front] > nums[rear]
if(nums[front]*nums[front] > nums[rear]*nums[rear]){
ans[p]=nums[front]*nums[front];
front++;
p--;
}else{
ans[p]=nums[rear]*nums[rear];
rear--;
p--;
}
}
return ans;
}
}
837

被折叠的 条评论
为什么被折叠?



