剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数在数组的前半部分,所有偶数在数组的后半部分。
题意理解 将数组排序奇数在前,偶数在后
- 使用双指针法,从数组开头l和结尾r开始遍历
- l,r均为索引,当l< r时循环急需,当nums[l]为基数时,l++;当nums[r]为基数时,r--;然后交换nums[r]和nums[l]的位置
- 直到循环结束
示例 输入:nums = [2, 7, 11, 15], target = 9 输出:[2, 7] 或者 [7, 2]
function exchange(nums) {
// 暴力
// const arr = []
// nums.forEach(item => {
// console.log( item % 2 ===0 );
// if (item % 2 === 0) {
// arr.push(item)
// }else{
// arr.unshift(item)
// }
// })
// return arr
// filter
// const arr1 = nums.filter(item=>item%2===1)
// const arr2 = nums.filter(item=>item%2===0)
// return [...arr1,arr2]
// 双指针
let l = 0,
r = nums.length - 1;
while (l < r) {
while (l < r && (nums[l] % 2 === 1)) {
l++
}
while (l < r && (nums[l] % 2 === 0)) {
r--
}
[nums[l], nums[r]] = [nums[r], nums[l]]
// 或者
// let current = nums[r]
// nums[r] = nums[l]
// nums[l] = current
}
return nums
}
剑指 Offer 57. 和为s的两个数字
输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。
提议理解 找出数据中两个数和为target的任意一对数字
- 暴力法超出时长,哈希慢,双指针最佳
- 一种标出数组是有序的这个很重要
- 这样就可以使用双指针,nums[left] + nums[right] === target,返回[nums[left], nums[right] ];nums[left] + nums[right] < target,则left++;nums[left] + nums[right] > target 则right --;
- 循环条件left < right
示例 输入:nums = [10, 26, 30, 31, 47, 60], target = 40 输出:[10, 30] 或者 [30, 10]
function twoSum(nums, target) {
// 暴力
// for (let i = 0; i < nums.length; i++) {
// const current = target - nums[i]
// if (nums.lastIndexOf(current)!==-1 && nums.lastIndexOf(current) !== i) {
// return [nums[i], current]
// }
// }
// return []
// Map
// let map = new Map()
// for (let i = 0; i < nums.length; i++) {
// map.set(nums[i], i)
// }
// for (let i = 0; i < nums.length; i++) {
// if(map.has(nums[i]) && map.has(target - nums[i])){
// return [nums[i],target - nums[i]]
// }
// }
// return []
// 双指针 最佳
let l = 0,
r = nums.length - 1;
while (l < r) {
if (nums[l] + nums[r] === target) {
return [nums[l], nums[r]]
} else if (target < nums[l] + nums[r]) {
r--
} else {
l++
}
}
return []
}
剑指 Offer 58 - I. 翻转单词顺序
输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. ",则输出"student. a am I"。
题意理解 翻转字符串,只反转字符串中单词的顺序,整个单词顺序不变,且反转后去句子两边空格,单词之间只有一个空格
- 双指针法,及r表示遍历当前单词的结尾,表示上个这个单词的开始
- 循环条件为l>=0
- 由于遍历原则,l会指向次单词的上个空格,所以字符截取时需要使用l+1,截取完后去除前面的空格,r-l;最后再去除句子开头结尾的空格
本人测试单项比多项块一点 示例 输入:s = "the sky is blue" 输出:"blue is sky the"
function reverseWords(s) {
// 双指针
// s = s.trim();
// let l = r = s.length - 1
// let arr = "";
// while (r >= 0) {
// while (l >= 0 && s[l] !== " ") {
// l--;
// }
// arr += " " + s.slice(l + 1, r + 1)
// while (s[l] === " ") {
// l--
// }
// r = l;
// }
// return arr.trim()
// 单项遍历
s = s.trim();
let right = s.length - 1;
let str = ""
while (right >= 0) {
let wordLength = 0;
while (right >= 0 && s[right] !== " ") {
wordLength++;
right--;
}
str += " " + s.substr(right + 1, wordLength)
while (right >= 0 && s[right] === " ") {
right--;
}
}
return str.trim()
}