- 小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
目录
- 冒泡排序
- 两数之和
([],Number) => []
一 冒泡排序
比较两个记录键值的大小,如果这两个记录键值的大小出现逆序,则交换这两个记录
function bubbleSort(arr){
for(let i = 1;i < arr.length;i++){
for(let j = i;j > 0;j--){
if(arr[j] < arr[j-1]){
[arr[j],arr[j-1]] = [arr[j-1],arr[j]];
}
}
}
return arr;
}
var arr = [3,4,2,1];
bubbleSort(arr); // [1, 2, 3, 4]
二 两数之和 ([],Number) => []
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 的那两个 整数,并返回它们的数组下标
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1]
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
可以遍历所有数字对,双重循环遍历当前值和另一个当前值与目标值是否相等,如果相等返回结果。
1) 遍历方式 ([],Number) => []
从第0个开始,依次和后面的数相加判断,不满足条件后, 再从第1个开始,依次和后面的数相加判断,直到,最后一个数. 优化: (可以少一次遍历)
外层for遍历条件可以修改为:i < nums.length-1
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
for (let i = 0; i < nums.length-1; i++) { // 优化: (可以少一次遍历) `外层for遍历条件` 可以修改为: `i < nums.length-1`
console.log('i:',i)
for (let j = i + 1; j < nums.length; j++) {
console.log('j:',j);
if (nums[i] + nums[j] === target) {
return [i,j];
}
}
}
};
var nums = [200,70,2];
var target = 290;
twoSum(nums, target);
执行过程:
i: 0 j: 1 2
i: 1 j: 2
i: 2 j: 不执行
- 第0个数和第二个,第三个相加,满足条件return
- 第1个数和第二个数相加,满足条件return
- 第2个数是最后一个数了,内层循环结束
var nums = [200,70,2];
var target = 270;
twoSum(nums, target);
2) 遍历方式 + indexOf
var twoSum = function(nums, target) {
for(let i = 0; i < nums.length; i++) {
var index = nums.indexOf(target-nums[i]);
if(index !== -1 && index !== i) {
return [i,index]
}
}
};
var nums = [2,3,4];
var target = 7;
twoSum(nums, target); // [1, 2]
3) 遍历方式 借助Map存储
var twoSum = function(nums, target) {
const map = new Map();
for (let i = 0; i < nums.length; i++) {
const diff = target - nums[i];
if (map.has(diff)) {
return [map.get(diff), i];
}
map.set(nums[i], i);
}
};
var nums = [2,3,4];
var target = 7;
twoSum(nums, target); // [1, 2]
4) 双指针方式
用两个指针进行查找,提高查找的效率
var twoSum = function(nums, target) {
if(!nums.length) return [];
let num = nums.slice(0);
nums.sort((x,y) => x-y);
let l = 0,r = nums.length-1;
while(l < r){
if(nums[l] + nums[r] === target) break;
else if(nums[l] + nums[r] < target){
l++;
}else{
r--;
}
}
l = num.indexOf(nums[l]);
r = num.indexOf(nums[r]) === l ? num.indexOf(nums[r],l+1) : num.indexOf(nums[r])
return [l,r];
};
var nums = [2,3,4];
var target = 7;
twoSum(nums, target);
5) 查找表法
-
在遍历的同时,记录一些信息,以省去一层循环,这是以
空间换时间的想法 -
需要记录
已经遍历过的数值和他对应的下标,可以借助查找表来实现 -
查找表常用的两个实现
哈希表平衡二叉树搜索
function twoSum(arr, target) {
var temp = []
let len = arr.length
for (let i = 0; i < len; i++) {
let dif = target - arr[i]
if (temp[dif] !== undefined) {
return [temp[dif], i]
}
temp[arr[i]] = i
}
};
let arr = [2, 3, 5, 9]
console.log(twoSum(arr, 7)) // [0, 2]
- 通过
let dif = target - arr[i]分别获取目标值与当前遍历元素的差值,如果这个差值作为哈希表的索引,能访问到有效元素,那么就说明当前遍历的i与temp[dif],就是要找的索引
[2, 3, 5, 9] 目标值是 7
- i = 0; dif = 7 - 2 = 5 此时temp[dif] = temp[5] = undefined
所以走 temp[arr[i]] = i; temp[2] = 0 // 哈希表存存储遍历过的数值和对应下标
- i = 1; dif = 7 - 3 = 4 此时 temp[dif] = temp[4] = undefined
所以走 temp[arr[i]] = i; temp[3] = 1 // 哈希表存存储遍历过的数值和对应下标
- i = 2; dif = 7 - 5 = 2 此时 temp[dif] = temp[2] = 0
此时这个差值作为哈希表的索引,能访问到有效元素,那么就说明当前遍历的i与temp[dif] ,就是要找的索引 , 所以return [temp[dif], i] 所以 最后结果是[0, 2]
参考
总结
双数之后实现思路:双层遍历|单层遍历(并借助对象存储)|双指针