开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 15 天,点击查看活动详情
题目
剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数在数组的前半部分,所有偶数在数组的后半部分。
示例:
输入:nums = [1,2,3,4]
输出:[1,3,2,4]
注:[3,1,2,4] 也是正确的答案之一。
分析
使用快慢指针,动态交换边界点值的位置
- 快指针遍历整个数组
- 遍历过程中,针对奇数值做处理
如果遇到偶数,慢指针不动,快指针继续遍历
如果遇到奇数,慢指针前移,由于慢指针始终处于边界处,会指向一个偶数值,需要交还给当前的奇数值,按此迭代下去
- 最后返回原数组
实现
var exchange = function(nums) {
let fast = 0
let slow = - 1
while (fast < nums.length) {
let cur = nums[fast]
if (isOdd(cur)) {
slow ++
[nums[fast], nums[slow]] = [nums[slow], cur]
}
fast ++
}
function isOdd (val) {
return val%2 !== 0
}
return nums
};
题目
剑指 Offer 57. 和为s的两个数字
输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。
示例:
输入:nums = [2,7,11,15], target = 9
输出:[2,7] 或者 [7,2]
分析一
本题可以利用一些数学的思维求解
利用哈希表方法,在遍历时,求出每个值相对应的差值,存储起来
并且同时判断当前值是不是在哈希表中,如果存在该值,就返回但前值和上一个值(上一个值可以用目标值减当前值反向得出)
实现
function twoSum(nums: number[], target: number): number[] {
let map: Map<number, null> = new Map()
for (let i = 0; i < nums.length; i++) {
if (map.has(nums[i])) {
return [target - nums[i], nums[i]]
} else {
map.set(target - nums[i], null)
}
}
};
分析二
因为该数组有序,可以使用双指针对撞遍历得出
- 定义首尾端点
- 遍历数组,当端点相遇时结束
- 使用某一端点计算差值对比
以左端点为例子(左端点为最小值),每次同时求出与目标值的差值
那么符合要求的点肯定在最右边
这时需要判断右侧的点,如果差值大于右端点的值,说明不存在符合当前最小值相对应的点,左端点右移
如果差值小于右端点的值,说明当前右端点的值无法找到与之对应的左端点,右端点左移
当差值为 0 时,返回这两个点
实现
function twoSum(nums: number[], target: number): number[] {
let left = 0
let right = nums.length - 1
while (left < right) {
let dif = target - nums[left]
if (dif > nums[right]) {
left ++
} else if (dif < nums[right]) {
right --
} else {
return [nums[left], nums[right]]
}
}
};