基本的数组双指针的题目大致如下:剩下两题,两题都是思想为主,与双指针沾边。
优势洗牌 (中等),fail
田忌赛马,打得过就打,打不过就拿自己的垃圾和对方的精锐互换。
我原本的思路:
是不对nums2排序,遍历nums2,每次都要与nums1逐个比较,而且涉及nums1的删除操作,感觉也行不通。
nums2 中元素的顺序不能改变,因为计算结果的顺序依赖 nums2 的顺序,所以不能直接对 nums2 进行排序,而是利用其他数据结构(保存原来索引和值的对象)来辅助。
[1,10,4,11]
map转成数组[值,原索引],再倒序排序
[ [ 11, 3 ], [ 10, 1 ], [ 4, 2 ], [ 1, 0 ] ]
核心思想将齐王和田忌的马按照战斗力排序,然后按照排名一一对比。如果田忌的马能赢,那就比赛(右指针),如果赢不了,那就换个垫底的来送人头(左指针),保存实力。而且不用考虑排名第二的与排名第一的比较,直接是索引一一对比,这是两个数组都排序的好处。 有一点贪心算法
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number[]}
*/
var advantageCount = function(nums1, nums2) {
let len = nums1.length
nums1.sort((x,y) => x-y) //升序
let obj2 = nums2.map((val, ind) => [val, ind])
obj2.sort((x,y) => y[0]-x[0]) //降序
// console.log(obj2)
let left=0, right=len-1; // nums1指针
let i=0; //obj2指针
let ans = new Array(len).fill(0)
// 从nums2最强的开始比, nums1比得过就自己上,否则用最小值混一下
for(let val2 of obj2){
if(val2[0] < nums1[right]) {
ans[val2[1]] = nums1[right]; //在nums2原顺序上填值
right--
}else{
ans[val2[1]] = nums1[left];
left++;
}
}
return ans;
};
986. 区间列表的交集 (中等)fail
- 什么情况下这两个区间没有交集:
if b2 < a1 or a2 < b1:
- 否命题——什么情况下,两个区间存在交集呢?
if b2 >= a1 and a2 >= b1:
- 两个区间存在交集的情况有哪些呢?
如果交集区间是[c1,c2],那么c1=max(a1,b1), c2=min(a2,b2)
- 数组的索引
i
i
i和
j
j
j肯定要前进(递增)的,什么时候应该前进呢?
取决于a2和b2的大小关系。
/**
* @param {number[][]} firstList
* @param {number[][]} secondList
* @return {number[][]}
*/
var intervalIntersection = function(firstList, secondList) {
let i=j=0, ans=[];
while (i<firstList.length && j<secondList.length){
let [a1, a2] = firstList[i];
let [b1, b2] = secondList[j];
if (b2>=a1 && a2>=b1) { //有交集
ans.push([Math.max(a1,b1), Math.min(a2,b2)])
}
b2>a2 ? i++ : j++
}
return ans;
};