1.
剑指 Offer 39 | 518 | 67.8% | 简单 |
法一:冒泡排序,取新数组中间的值,中位数元素 一定为众数
/**
* @param {number[]} nums
* @return {number}
*/
var majorityElement = function(nums) {
nums.sort(function(a, b) {
return a - b; //升序。
});
return nums[Math.floor(nums.length / 2)];
};
注意这里sort()中添加一个函数,防止个位数以上的数字参与进来排序时出现的问题。此题不加也可以。
法二:投票算法
原理:从头开始,不断消除不相同的元素,最后留下的元素就是出现次数>n/2的数字。
例如[1,2,3,4,2,2,2],从头开始,1和2消去,3和4消去,最后留下3个2不会被消去
时间复杂度 O(N),空间复杂度 O(1)
var majorityElement = function(nums) {
let count = 1; //已经从第0位开始,所以计数器起始为1
let most = nums[0];//暂且把结果当做第0位
for(let i = 1; i < nums.length; i++) {
//i从第1位开始
if(count == 0) most = nums[i];
if(nums[i] == most) {
count ++;
} else {
count --;
}
}
return most;
};
实际上,如果给的数组是[1,2,3,4,2,2],虽然2出现次数没有大于n/2,但由于3和4互相消掉,所以最后仍然输出2,也就是说,此方法可以通过所有符合题意的题(本题所有案例),但还能通过一些实际并不符合题意的题。
2.
剑指 Offer 57 | 377 | 65.5% | 简单 |
输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[2,7] 或者 [7,2]
示例 2:
输入:nums = [10,26,30,31,47,60], target = 40
输出:[10,30] 或者 [30,10]
法一:for循环+indexOf,超出时间限制,通过29/36
即使每次indexOf从i开始,也会超出时间限制
var twoSum = function(nums, target) {
let arr = [];
for(let i = 0; i < nums.length; i++) {
let index = nums.indexOf(target - nums[i],i);
if(index == -1) {
continue;
}else {
arr.push(nums[i]);
arr.push(nums[index]);
break;
}
}
return arr;
};
由于题目给的是递增排序的数组,我的法一没考虑到,所以在时间上一定有问题。
法二:双指针
while循环,终止条件是i !== j
sum = 首尾两个指针i、j所指向的值的和
sum > target => j--
sum < target => i++
等于的时候直接return。
var twoSum = function(nums, target) {
let i = 0;
let j = nums.length-1;
while(i !== j) {
let sum = nums[i] + nums[j];
if (sum > target) {
j--;
} else if (sum < target) {
i++;
} else {
// break;
return [nums[i],nums[j]]
}
}
// return [nums[i],nums[j]]
};
3.
剑指 Offer 64 | 871 | 85.1% | 中等 |
求 1+2+...+n
,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
示例 1:
输入: n = 3 输出: 6
递归:
var sumNums = function(n) {
// return (1+n)*n/2
// 递归:
return n && n + sumNums(n-1)
};