力扣面试150题经典
88. 合并两个有序数组
思路: 比较两个数组中最大的数(数组是非递减的), 选取大的那个, 从nums1的最后边赋值.
/**
* @param {number[]} nums1
* @param {number} m
* @param {number[]} nums2
* @param {number} n
* @return {void} Do not return anything, modify nums1 in-place instead.
*/
var merge = function (nums1, m, nums2, n) {
let i = m - 1
let j = n - 1
let k = m + n - 1 // 指向nums1的最后一个位置
while (j >= 0) {
if (nums1[i] > nums2[j]) {
nums1[k] = nums1[i]
// i用掉了, i--
i--
} else {
nums1[k] = nums2[j]
// j用掉了, j--
j--
}
k-- // 反正最后一个位置都会被用掉的, --
}
console.log(nums1);
}
// 测试用例
merge([1,3,9,0,0],3,[2,10],2)
.
.
输出结果:
.
.
.
.
27. 移除元素
思路:使用左右指针,右指针去遍历,最后返回的左指针的位置即为新数组的长度
/**
* @param {number[]} nums
* @param {number} val
* @return {number}
*/
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
}
.
.
.
.
.
26. 删除有序数组中的重复项
思路:读题可知,所有重复项元素都应相邻,使用快慢指针。
/**
* @param {number[]} nums
* @return {number}
*/
var removeDuplicates = function (nums) {
let slow = 0
for (let right = 1; right < nums.length; right++) {
if (nums[right] !== nums[slow]) {
slow++
nums[slow] = nums[right]
}
}
return slow + 1
}
.
.
.
.
.
80. 删除有序数组中的重复项2
思路:使用快慢指针,设置theSame表示重复数字出现的次数。别忘了走到不同数字之后theSame重置方便下次使用。
/**
* @param {number[]} nums
* @return {number}
*/
var removeDuplicates = function (nums) {
let len = nums.length
if (len < 3) {
return len
}
let slow = 0
let theSame = 0
for (let fast = 1; fast < len; fast++) {
if (nums[fast] !== nums[slow]) {
slow++
nums[slow] = nums[fast]
theSame = 0
} else {
theSame++
if (theSame === 1) {
slow++
nums[slow] = nums[fast]
}
}
}
return slow + 1
}
const nums = [0, 0, 1, 1, 1, 1, 2, 3, 3]
console.log(removeDuplicates(nums))
.
.
.
.
.
169. 多数元素
思路1:暴力解法,依次取出元素并遍历对比,找到多数就return,找不到就循环下一个元素。【不推荐,复杂度高】
/**
* @param {number[]} nums
* @return {number}
*/
var majorityElement = function (nums) {
let len = nums.length
let i, j
let count = 0
for (i = 0; i < len; i++) {
for (j = 0; j < len; j++) {
if (nums[i] === nums[j]) {
count++
}
}
if (count > len / 2) {
return nums[i]
} else {
count = 0
}
}
}
.
.
.
思路2:将数组排序后,返回的中间值即为多数
/**
* @param {number[]} nums
* @return {number}
*/
var majorityElement = function(nums) {
nums.sort((a, b) => a - b)
return nums[Math.round(nums.length / 2)-1]
};
.
.
.
思路3:摩尔投票法,使用candidate和cnt
/**
* @param {number[]} nums
* @return {number}
*/
var majorityElement = function (nums) {
let candidate
let count = 0
for (let num of nums) {
if (count === 0 || num === candidate) {
count++
candidate = num
} else {
count--
}
}
return candidate
}
nums = [1, 1, 2, 2, 1, 1]
console.log(majorityElement(nums))
注意:这里的题目是“多数”而非“众数”,也就是数量要大于n/2,我一开始用的实验数组为[1, 1, 3, 2, 3, 1],输出3。
.
.
.
.
169. 轮转数组
思路1: 拷贝一份数组, 要轮转几个就换几个
/**
* @param {number[]} nums
* @param {number} k
* @return {void} Do not return anything, modify nums in-place instead.
*/
var rotate = function (nums, k) {
let len = nums.length
let copy = [...nums]
// 如果k>len会报错, 输出undefined, 处理一下
k %= len
for (let i = 0; i < len; i++) {
nums[i] = copy[(i + len - k) % len]
}
return nums
}
console.log(rotate([1, 2, 3, 4, 5, 6, 7], 3))
注意点:
let copy = [...nums]
这里是要拷贝一份, 不要写成引用一份let copy = nums
- 如果k>len会报错, 输出undefined, 处理一下
k %= len
.
.
思路2: 三段翻转
/**
* @param {number[]} nums
* @param {number} k
* @return {void} Do not return anything, modify nums in-place instead.
*/
var rotate = function (nums, k) {
let len = nums.length
if (k > len) {
k %= len
}
reverse(nums, 0, len - k - 1)
reverse(nums, len - k, len - 1)
reverse(nums, 0, len - 1)
return nums
}
const reverse = function (nums, from, to) {
let temp
while (from < to) {
temp = nums[from]
nums[from] = nums[to]
nums[to] = temp
from++
to--
}
return nums
}
console.log(rotate([1, 2, 3, 4, 5, 6, 7], 3))
.
.
.
.
.
121. 买卖股票的最佳时机
思路1: 暴力解法 j>i 作差保留最大值
/**
* @param {number[]} prices
* @return {number}
*/
var maxProfit = function (prices) {
let len = prices.length
let i, j
let mostProfit = 0,
tempProfit = 0
for (i = 0; i < len - 1; i++) {
for (j = i + 1; j < len; j++) {
tempProfit = prices[j] - prices[i]
if (tempProfit > mostProfit) {
mostProfit = tempProfit
}
}
}
return mostProfit
}
console.log(maxProfit([7,1,5,3,6,4]))
注意点: prices很大的话, 超出时间限制
.
.
思路2: 一次遍历, 遍历一遍数组, 计算每次到当天为止的minPrice和mostProfit
活在当下, 如果这一天你还没买股票, 你肯定会想, 你在哪一天能够以历史低价收购股票, 又能在哪一天高价抛出呢
/**
* @param {number[]} prices
* @return {number}
*/
var maxProfit = function (prices) {
let len = prices.length
let minPrice = prices[0],
mostProfit = 0
for (let i = 0; i < len; i++) {
if (prices[i] < minPrice) {
minPrice = prices[i]
} else if (prices[i] - minPrice > mostProfit) {
mostProfit = prices[i] - minPrice
}
}
return mostProfit
}
console.log(maxProfit([7, 1, 5, 3, 6, 4]))