大厂高频算法考点--双指针
数指针是一个很常见的技巧,为大家提供了leetcode的练习题和答案。
问题一:922. 按奇偶排序数组 II - 力扣(LeetCode)
class Solution {
public int[] sortArrayByParityII(int[] nums) {
//题目写了这个数组就是大与2的
//分析题目,将技术放置在下标是奇数的位置 偶数放置在下表是偶数的位置
//双指针的方式解决这个问题
//在考虑一个问题,是将双指针设置为标
int even =0;
int odd=1;
while(even<nums.length){
while(nums[even]%2!=0){
swap(nums,even,odd);
if(odd+2>nums.length-1){
break;
}else{
odd+=2;
}
}
even+=2;
}
return nums;
}
private void swap(int[] arr,int a,int b){
int temp =arr[a];
arr[a]=arr[b];
arr[b]=temp;
}
}
问题二:287. 寻找重复数 - 力扣(LeetCode)
class Solution {
public int findDuplicate(int[] nums) {
//这个问题真的很像单链表的查找入环节点 就是将他包装为单链表,但是如何包装呢
//使用数组和下标进行包装 我们吧当前位置的值设置为就是他下一个位置的下标
if(nums.length<=2){
return nums[0];
}
int slow=nums[0];
int fast=nums[nums[0]];
while(slow!=fast){
slow=nums[slow];
fast=nums[nums[fast]];
}
fast=0;
while(fast!=slow){
fast=nums[fast];
slow=nums[slow];
}
return fast;//指针的值是下标
}
}
问题三:42. 接雨水 - 力扣(LeetCode)
方法一:浪费空间,未经优化
class Solution {
public int trap(int[] height) {
//采取两种方式
//直接在创建两个数组 记录每个点左右的的比他大的值
//第一个数组是记录在0~i位置上的最大值
//第二个数组就是记录在i~n-1的最大值
//如果求解i的位置的话,就直接使用数组lmax的i-1的值,和rmax的i+1的值。
int n=height.length;
int[] lmax=new int[n];
int[] rmax=new int[n];
lmax[0]=height[0];
for(int i=1;i<n;i++){
lmax[i]=Math.max(lmax[i-1],height[i]);
}
rmax[n-1]=height[n-1];
for(int i=n-2;i>=0;i--){
rmax[i]=Math.max(rmax[i+1],height[i]);
}
int ans=0;
for(int i=1;i<n-1;i++){
ans+=Math.min(lmax[i-1],rmax[i+1])-height[i]>=0?Math.min(lmax[i-1],rmax[i+1])-height[i]:0;
}
return ans;
}
}
方法二:不会创建新的数组
接雨水规律:如果现在右侧的最大高度>左侧,那就计算左侧的接雨水点,反之亦然
public static int trap(int[] height){
//优化的版本,不会创建新的数组,但是需要思考的过程
//总结就是一句话:如果现在右侧的最大高度>左侧,那就计算左侧的接雨水点,反之亦然
//因为如果现在右侧的高度已经大于左侧了,木桶原理,受限的原因一定是短板,右侧的高度一定不会比现在小,但是左面的高度不会半大,已经确定
//我能确定的最大值就是最小值
int n=height.length;
int l=0;
int r=n-1;
int lmax=height[0];
int rmax=height[n-1];
int ans=0;
while(l<r&&(l<n-1&&r>0)){
if(lmax<=rmax){
l++;
ans+=lmax-height[l]>=0?lmax-height[l]:0;
lmax=Math.max(height[l],lmax);
}else{
r--;
ans+=rmax-height[r]>=0?rmax-height[r]:0;
rmax=Math.max(height[r],rmax);
}
}
return ans;
}
问题四:881. 救生艇 - 力扣(LeetCode)
class Solution {
public int numRescueBoats(int[] people, int limit) {
Arrays.sort(people);//将数组排序
int l=0,r=people.length-1;
int ans=0;
while(l<=r){
if(people[l]+people[r]<=limit){
l++;
r--;
ans++;
}else{
r--;ans++;
}
}
return ans;
}
}
问题五:11. 盛最多水的容器 - 力扣(LeetCode)
class Solution {
public int maxArea(int[] height) {
//思路就是短板效应,如果你现在得值是小的,那你就计算面积
int l = 0;
int r =height.length-1;
int ans=0;
while(l<=r){
if(height[l]<=height[r]){
ans=Math.max((r-l)*height[l],ans);
l++;
}else{
ans=Math.max((r-l)*height[r],ans);
r--;
}
}
return ans;
}
}
问题六:475. 供暖器 - 力扣(LeetCode)
方法一:暴力方式
因为数组的长度是10^4所以即使是n*n的操作也不会超时,所以这道题可以暴力,但是如果暴力的话效率低
public int findRadius(int[] houses, int[] heaters) {
int ans=0;
//无需创建数组,直接相减就行
for(int i=0;i<houses.length;i++){
int count=Integer.MAX_VALUE;
for(int j=0;j<heaters.length;j++){
count=Math.min(count,getNum(houses[i]-heaters[j]));
}
ans=Math.max(count,ans);
}
return ans;
}
public int getNum(int n){
return n>=0?n:-n;
}
方法二:双指针
我感觉这个解体方法很美妙
class Solution {
public int findRadius(int[] houses, int[] heaters) {
Arrays.sort(houses);
Arrays.sort(heaters);
int ans=0;
//使用双指针解决问题
//将r指针的移动就是在查找到位置是才会移动
//特别注意的是我们收集的答案时同一个房间的最短距离,但是房间之间我们收集的是最大值
//注意这个数组的数据必须是有序的
int l =0;
int r=0;
for(l=0;l<houses.length;l++){
while(!best(houses,heaters,l,r)){//这里面直接比较出来房间里的最小的值了
r++;
}
//现在直接比较房间与房间之间的最大值
ans=Math.max(ans,Math.abs(houses[l]-heaters[r]));
}
return ans;
}
public boolean best(int[] houses,int[] heaters,int i,int j){
//之里面一定是> 我么的设定就是即使时相等时,就必须要前进
return j==heaters.length-1 ||Math.abs(houses[i]-heaters[j+1])- Math.abs(houses[i]-heaters[j])>0;
}
}
问题七41. 缺失的第一个正数 - 力扣(LeetCode)
class Solution {
//整体的思路如下
//因为数值在设计这个题目时设定,如果长度是n的数组,那他每个位置的值就在n-1处,所以最佳状态
//是缺的就是第n+1的数字
//使用双指针去解决问题,将l指针放置在0位置,r指针放置在n位置,注意是n位置,不是n-1,我们将要维护一个无效区
//哪几种情况数值无效,
//1.数值大小《=0 或者是当前的下表是3 但是这个数比4小
//2.当前的之大于r
//3.如果当前值就是n在n-1位置,l++
//如果现在的数字是4 但是你的三位置放置了4 那就是垃圾
public int firstMissingPositive(int[] arr) {
int l=0;
int r=arr.length;
while(l<r){
if(arr[l]==l+1){
l++;
}else if (arr[l]>r||arr[l]<=l||arr[l]==arr[arr[l]-1]){
swap(arr,l,--r);
}else{
swap(arr,l,arr[l]-1);//现在就是数值时合法的,该如何计算 5
}
}
return l+1;
}
public void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
原文地址:https://blog.csdn.net/hdk5855/article/details/142921522
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!