调整数组顺序
剑指 Offer 21. 调整数组顺序使奇数位于偶数前面 - 力扣(LeetCode)
方法一:双指针
思路:
设定两个指针,第一个指针left从数组第一个元素出发,向尾部前进,如果遇到的是奇数,说明该元素已调整好,继续向右遍历,直到遇到一个偶数;第二个指针right从数组的最后一个元素出发,向头部前进,直到遍历到奇数时,交换两个数的位置
var exchange = function(nums) {
let left = 0, right = nums.length -1
while(left < right) {
while(left < right && nums[left] % 2 === 1) {
left++
}
while(left < right && nums[right] % 2 === 0) {
right--
}
if(left < right) {
//交换
[nums[left], nums[right]] = [nums[right], nums[left]]
left++
right--
}
}
return nums
};
- 时间复杂度: O(n),只遍历一次
- 空间复杂度: O(1)
方法二:双指针+一次遍历
思路: 新建一个保存结果的数组,长度为nums的长度,遍历nums,遇到奇数则从res的左侧开始替换元素,遇到偶数就从res的右侧替换元素。
var exchange = function(nums) {
let res = new Array(nums.length).fill(0)
let left = 0, right = nums.length -1
for(let num of nums) {
if(num % 2 !== 0) {
res[left++] = num
}else {
res[right--] = num
}
}
return res
};
- 时间复杂度: O(n),只遍历一次
- 空间复杂度: O(1),结果不计入空间复杂度
方法三:两次遍历
新建一个数组 res 用来保存调整完成的数组。遍历两次nums,第一次遍历时把所有奇数依次追加到 res 中,第二次遍历时把所有偶数依次追加到res 中。
移除元素
题目描述:给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
方法: 双指针法
思路:使用快慢指针,慢指针指向将要赋值的位置,快指针指向将要进行处理的元素
如果快指针指向的元素不等于 val,它一定是输出数组的一个元素,我们就将快指针指向的元素复制到慢指针位置,然后将快慢指针同时右移;
如果右指针指向的元素等于val,它不能在输出数组里,此时慢指针不动,快指针右移一位。
整个过程保持不变的性质是:区间[0,left) 中的元素都不等于val。当快慢指针遍历完输入数组以后,left 的值就是输出数组的长度。
这样的算法在最坏情况下(输入数组中没有元素等于val),快慢指针各遍历了数组一次
代码实现
var removeElement = function(nums, val) {
let left = 0
for(let right = 0; right < nums.length; right++) {
if(nums[right] !== val) {
nums[left] = nums[right]
left++
}
}
return left
};
- 时间复杂度: O(n),只需要遍历该序列至多两次
- 空间复杂度: O(1)
注意:不能使用排序数组的双指针法,因为当输入数组的元素全为目标值,需要删除时,就会出错
//下面这种写法不能通过全部样例
var removeElement = function(nums, val) {
let left = 0, right = nums.length - 1
while(left < right) {
while(left < right && nums[left] !== val) {
left++
}
while(left < right && nums[right] === val) {
right--
}
if(left < right) {
[nums[left], nums[right]] = [nums[right], nums[left]]
left++
right--
}
}
return left + 1
};
找到和为给定整数的三个连续整数
2177. 找到和为给定整数的三个连续整数 - 力扣(LeetCode)
题目描述:
给一个整数num,返回三个连续的整数,它们的和为num,如果num无法被表示成三个连续整数的和,返回一个空数组。
var sumOfThree = function(num) {
if(num % 3 === 0) {
return [num / 3 -1, num/3, num/3+1]
}
return []
};
- 时间复杂度: O(1)
- 空间复杂度: O(1)
和为s的连续正整数序列
剑指 Offer 57 - II. 和为s的连续正数序列 - 力扣(LeetCode)
题目: 输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
例如:输入15,有序1+2+3+4+5 = 4+5+6 = 7+8 = 15 所以打印出3个连续序列1-5,5-6和7-8。
var findContinuousSequence = function(target) {
let res = []
let tmp = [1,2] //窗口
let l = 1, r = 2
let sum = 3
while(r < target) {
while(sum < target && r < target) {
tmp.push(++r)
sum += r
}
while(sum > target && l < r) {
tmp.shift()
sum -= l
l++
}
if(sum === target && tmp.length > 1) {
res.push(tmp.slice())
tmp.shift()
sum -= l
l++
}
}
return res
};