用二分查找来做一个简单题 室友说做不了,我说行,我做给你看
哈喽哈喽,我是你们的金樽清酒,很高兴能把我自己学习的历程分享在网上,把自己学到的知识分享给大家,最近刚学了二分查找,室友说你不是刚学了二分查找嘛,我给你一道题,你能用二分写出两个测试用例嘛,这道题是用二分写不出来的,我看题解都没有二分。好,那我就写给他看。
先了解一下二分查找
二分查找是一个可以快速检索数组某元素下标的算法,在我往期的文章里面有(跟着代码随想录 一 二分查找 - 掘金 (juejin.cn))
先看一下题
给你两个整数数组 nums1
和 nums2
,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。
示例 1:
css
输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2,2]
示例 2:
css
输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [4,9]
提示:
1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 1000
题目分析 以一个数组作为查询的数组,另一个数组里面的元素作为target,就可以用二分查找来写
js
var intersect = function (nums1, nums2) {
let arr = []
nums1.sort((a, b) => a - b)
nums2.sort((a, b) => a - b)
if (nums1.length >= nums2.length) {
for (let i = 0; i < nums2.length; i++) {
if (erfen(nums1, nums2[i]) !== -1) {
let index = erfen(nums1, nums2[i])
arr.push(nums1[index])
nums1.splice(index, 1)
}
}
return arr
} else
if (nums1.length < nums2.length) {
for (let i = 0; i < nums1.length; i++) {
if (erfen(nums2, nums1[i]) !== -1) {
let index = erfen(nums2, nums1[i])
arr.push(nums2[index])
nums2.splice(index, 1)
}
}
return arr
}
};
function erfen(arr1, target) {
let mid, left = 0
let right = arr1.length - 1
while (left <= right) {
mid = left + ((right - left) >> 1)
if (arr1[mid] > target) {
right = mid - 1
} else if (arr1[mid] < target) {
left = mid + 1
}
else if (arr1[mid] == target) {
return mid
}
}
return -1
}
这是我写的代码,因为刚开始只是想通过两个用例,所以比较了数组长度,其实是没有必要的。 用二分查找找到下标,再把该下标的值push进新数组,然后删除掉,这是避免重复元素,存在重复元素二分查找会出问题,只能找到前面或后面。这样其实就可以了。
室友没有我写的那么复杂,可以优化的,删除重复元素后就没有必要比数组长短了。室友当时没有考虑删除元素的问题。
改进版
js
var intersect = function (nums1, nums2) {
nums2.sort((a, b) => a - b)
nums1.sort((a, b) => a - b)
let sum = []
let left = 0
for (let i = 0; i < nums1.length; i++) {
let number = nums1[i]
let right = nums2.length - 1
while (left <= right) {
let midle = Math.ceil((left + right) / 2)
if (nums2[midle] > number) {
right = midle - 1
} else if (nums2[midle] < number) {
left = midle + 1
} else if (nums2[midle] === number) {
let index = nums2.splice(midle, 1)
sum.push(index)
break
}
}
}
return sum
}
双指针法
js
let intersect = function (nums1, nums2) {
nums1.sort((a, b) => a - b);
nums2.sort((a, b) => a - b);
let l = 0, r = 0, ans = [];
while (l < nums1.length && r < nums2.length) {
if (nums1[l] === nums2[r]) {
ans.push(nums1[l]);
l++;
r++;
} else nums1[l] < nums2[r] ? l++ : r++;
}
return ans;
};
作者:御三五 🥇
链接:https://leetcode.cn/problems/intersection-of-two-arrays-ii/solutions/683821/ha-xi-biao-liang-ge-shu-zu-de-jiao-ji-ii-fkwo/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。