编程导航算法村第三关 | 白银挑战
原地移除所有数值等于 val 的元素
LeetCode27.给你一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,并返回移除后数组的新长度。要求:不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素
- 使用快慢指针方法,slow执行的元素就是新数组
public int removeElement(int[] nums, int val) {
int slow = 0;
// int fast=0;
for (int fast = 0; fast < nums.length; fast++) {
if (nums[fast] != val) {
nums[slow] = nums[fast];
slow++;
}
}
return slow;
}
删除有序数组中的重复项
- slow指向新数组,fast负责遍历
- 如果fast能到达末尾,则直接将该元素赋值给slow数组
- 判断fast与fast+1是否相等
- 如果相等,fast++跳过所有的重复值,只保留第一个
public int removeDuplicates(int[] nums) {
int slow = 0;
for (int fast = 0; fast < nums.length; ) {
// 如果到达最后一个
if (fast == nums.length - 1) {
// if (nums[fast] != nums[fast - 1]) {
nums[slow] = nums[fast];
slow++;
break;
// }
}
if (nums[fast] != nums[fast + 1]) {
nums[slow] = nums[fast];
slow++;
fast++;
} else if (nums[fast] == nums[fast + 1]) {
int temp = nums[fast];
nums[slow] = temp;
slow++;
fast++;
while (nums[fast] == temp) {
fast++;
if (fast >= nums.length) {
break;
}
}
}
}
return slow;
}
- 优化后
- slow-1是新数组的最后一个元素
public int removeDuplicates(int[] nums) {
int slow = 1;
for (int fast = 0; fast < nums.length; fast++) {
if (nums[fast] != nums[slow - 1]) {
nums[slow]=nums[fast];
slow++;
}
}
return slow;
}
元素奇偶移动专题
给你一个整数数组 nums,将 nums 中的的所有偶数元素移动到数组的前面,后跟所有奇数元素。
返回满足此条件的 任一数组 作为答案。
示例 1:
输入:nums = [3,1,2,4]
输出:[2,4,3,1]
解释:[4,2,3,1]、[2,4,1,3] 和 [4,2,1,3] 也会被视作正确答案。
示例 2:
输入:nums = [0]
输出:[0]
提示:
1 <= nums.length <= 5000
0 <= nums[i] <= 5000
Related Topics 数组 双指针 排序 👍 360 👎 0
public int[] sortArrayByParity(int[] nums) {
int left = 0;
int right = nums.length - 1;
while (left < right) {
// 找到奇数
if (nums[left] % 2 != 0) {
// 移动right直到找到偶数
while (right > left) {
if (nums[right] % 2 == 0) {
// 交换right与left的顺序
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
break;
}
right--;
}
}
left++;
}
return nums;
}
数组轮转问题
给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
示例 1:
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]
示例 2:
输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释:
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]
提示:
1 <= nums.length <= 10⁵
-2³¹ <= nums[i] <= 2³¹ - 1
0 <= k <= 10⁵
进阶:
尽可能想出更多的解决方案,至少有 三种 不同的方法可以解决这个问题。
你可以使用空间复杂度为 O(1) 的 原地 算法解决这个问题吗?
Related Topics 数组 数学 双指针 👍 1882 👎 0
以下这种解法错误,无法解决
[-1] 2的情况
public void rotate(int[] nums, int k) {
int[] temp = new int[k];
int j = 0;
for (int i = nums.length - k; i < nums.length; i++, j++) {
temp[j] = nums[i];
}
// 将剩余元素向后移动k位
for (int i = nums.length - k - 1; i >= 0; i--) {
nums[i + k] = nums[i];
}
for (int i = 0; i < k; i++) {
nums[i] = temp[i];
}
}
- 通过两轮翻转的方法
- 例如
- [1,2,3,4,5,6,7]
3 - 整体翻转变为:7 6 5 4 3 2 1
- 翻转0到k-1 5 6 7 4 3 2 1
- 翻转k到length-1 5 6 7 1 2 3 4
public void rotate(int[] nums, int k) {
// 计算k在nums中的地址
k %= nums.length;
// 整体翻转
reverse(nums, 0, nums.length - 1);
// 翻转0——k-1
reverse(nums,0, k-1);
// 翻转后一部分 k——nums.length - 1
reverse(nums,k, nums.length - 1);
}
public void reverse(int[] nums, int start, int end) {
while (start < end) {
int temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
start++;
end--;
}
}
汇总区间
给定一个 无重复元素 的 有序 整数数组 nums 。
返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表 。也就是说,nums 的每个元素都恰好被某个区间范围所覆盖,并且不存在属于某个范围但不属于
nums 的数字 x 。
列表中的每个区间范围 [a,b] 应该按如下格式输出:
“a->b” ,如果 a != b
“a” ,如果 a == b
示例 1:
输入:nums = [0,1,2,4,5,7]
输出:[“0->2”,“4->5”,“7”]
解释:区间范围是:
[0,2] --> “0->2”
[4,5] --> “4->5”
[7,7] --> “7”
示例 2:
输入:nums = [0,2,3,4,6,8,9]
输出:[“0”,“2->4”,“6”,“8->9”]
解释:区间范围是:
[0,0] --> “0”
[2,4] --> “2->4”
[6,6] --> “6”
[8,9] --> “8->9”
提示:
0 <= nums.length <= 20
-2³¹ <= nums[i] <= 2³¹ - 1
nums 中的所有值都 互不相同
nums 按升序排列
Related Topics 数组 👍 268 👎 0
- 将slow作为连续区间的起始位置,fast作为终点位置
public List<String> summaryRanges(int[] nums) {
ArrayList<String> result = new ArrayList<>();
int slow = 0;
// [0,1,2,4,5,7]
for (int fast = 0; fast < nums.length; fast++) {
if (fast + 1 == nums.length || nums[fast] + 1 != nums[fast + 1]) {
if (slow==fast){
result.add(nums[slow]+"");
}else {
result.add(nums[slow]+"->" + nums[fast]);
}
slow = fast + 1;
}
}
return result;
}
字符串替换空格问题
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
示例 1:
输入:s = “We are happy.”
输出:“We%20are%20happy.”
限制:
0 <= s 的长度 <= 10000
Related Topics 字符串 👍 512 👎 0
public String replaceSpace(String s) {
// char[] chars = new char[];
int cout = s.length();
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == ' ') {
cout+=2;
}
}
char[] chars = new char[cout];
for (int i = 0; i < s.length(); i++) {
// if (s.charAt(i) == ' ') {
chars[i] = s.charAt(i);
// }
}
int slow = cout - 1;
for (int fast = s.length()-1; fast >= 0; fast--) {
if (chars[fast] != ' ') {
chars[slow] = chars[fast];
slow--;
} else {
chars[slow--] = '0';
chars[slow--] = '2';
chars[slow--] = '%';
}
}
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < cout; i++) {
stringBuilder.append(chars[i]);
}
return stringBuilder.toString();
//
}