Leetcode每日刷题:(二分查找+双指针+hashmap)&(数组+链表+字符串)

1.二分查找右边界:爱吃香蕉的珂珂

在这里插入图片描述

class Solution {
    public int minEatingSpeed(int[] piles, int h) {
        //使用二分查找法寻找速度的左边界,即最小速度

        //速度的左右边界,最大速度就是数组的最大值,因为一小时吃完这堆香蕉不会再吃更多的香蕉
        int left=1,right=getMax(piles)+1;
        while(left<right){
            int mid=left+(right-left)/2;
            if(canEatAll(piles,mid,h)){
                right=mid;
            }else{
                left=mid+1;
            }
        }
        return left;
    }


    //求速度为speed时,吃完香蕉需要的时间总和是否小于等于时间h
    //在满足这个条件的速度里使用二分查找找到最小速度
    public boolean canEatAll(int[] piles,int speed,int h){
        int res=0;
        for(int pile:piles){
            res=res+(pile/speed)+((pile%speed==0)?0:1);
        }
        return res<=h;
    }

    //求最大值
    public int getMax(int[] piles){
        int res=0;
        for(int i:piles){
            res=Math.max(res,i);
        }
        return res;
    }
}

2.快慢双指针+hashset:环形链表

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
        //1.使用快慢双指针
        ListNode slow=head,fast=head;
        while(fast!=null && fast.next!=null){
            fast=fast.next.next;
            slow=slow.next;
            if(fast==slow){
                return true;
            }
        }
        return false;
        //2.使用hashset
        // Set<ListNode> set=new HashSet<>();
        // while(head!=null){
        //     if(set.contains(head)){
        //         return true;
        //     }
        //     set.add(head);
        //     head=head.next;
        // }
        // return false;
    }
}

3.快慢双指针:环形链表2

在这里插入图片描述
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if(head!=null && head.next==null){
            return null;
        }

        ListNode slow=head,fast=head;
        
        while(fast!=null && fast.next!=null){
            fast=fast.next.next;
            slow=slow.next;
            if(fast==slow) break;//找到环的入口
        }
        //如果没有环,则经过while循环之后fast和slow指向位置不同,则返回null
        if(fast!=slow){
            return null;
        }
        //寻找环的入口
        //如果是环形链表带小尾巴,就会进入while循环寻找环的入口;
        //如果不带尾巴,则上个while循环fast和slow总会在入口处(head)相遇:因为fast速度是slow的二倍,相遇时fast走了两圈,slow走了一圈,相遇处就是head,则不会进入下面的while循环。
        fast=head;
        while(fast!=slow){
            fast=fast.next;
            slow=slow.next;
        }
        return fast;
    }
}

4.快慢双指针:链表的中间节点

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode middleNode(ListNode head) {
        ListNode fast=head,slow=head;
        while(fast!=null && fast.next!=null){
            fast=fast.next.next;
            slow=slow.next;
        }
        return slow;
    }
}

5.快慢双指针:链表中倒数第k个节点

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode getKthFromEnd(ListNode head, int k) {
        if(head==null){
            return null;
        }
        //防止k超过链表长度
        int len=0;
        ListNode temp=head;
        while(temp!=null){
            temp=temp.next;
            len++;
        }
        if(k!=len){
            k=k%len;
        }

        ListNode fast=head,slow=head;
        //fast先走k步
        while(k>0){
            fast=fast.next;
            k--;
        }
        //一起走,最后slow的位置就是倒数第k个节点
        while(fast!=null){
            fast=fast.next;
            slow=slow.next;
        }

        return slow;

    }
}

6.快慢双指针:删除有序数组中的重复项

在这里插入图片描述

class Solution {
    public int removeDuplicates(int[] nums) {
        //使用快慢指针,快指针遇到不同的数就和慢指针交换,最后慢指针以及慢指针之前的数组部分都是不重复的
        int n=nums.length;
        int fast=0,slow=0;
        while(fast<n){
            if(nums[fast]!=nums[slow]){
                slow++;
                nums[slow]=nums[fast];
            }
            fast++;
        }
        return slow+1;
    }
}

7.快慢双指针:删除排序链表中的重复元素

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        if(head==null) return null;
        ListNode fast=head,slow=head;
        while(fast!=null){
            if(fast.val!=slow.val){
                slow.next=fast;
                slow=slow.next;
            }
            fast=fast.next;
        }
        slow.next=null;//处理末尾
        return head;
    }
}

8.快慢双指针:移除元素

在这里插入图片描述

class Solution {
    public int removeElement(int[] nums, int val) {
        int n=nums.length;
        if(n==0) return 0;

        int fast=0,slow=0;
        while(fast<n){
            if(nums[fast]!=val){
                nums[slow]=nums[fast];
                slow++;
            }
            fast++;
        }
        return slow;
    }
}

9.快慢双指针:移动零

在这里插入图片描述

class Solution {
    public void moveZeroes(int[] nums) {
        int n=nums.length;
        if(n==0) return;

        int fast=0,slow=0;
        while(fast<n){
            if(nums[fast]!=0){
                int temp=nums[slow];
                nums[slow]=nums[fast];
                nums[fast]=temp;
                slow++;
            }
            fast++;
        }
    }
}

10.hashmap:两数之和

在这里插入图片描述

class Solution {
    public int[] twoSum(int[] nums, int target) {
        //使用hashmap
        int[] res=new int[2];
        Map<Integer,Integer> map=new HashMap<>();
        for(int i=0;i<nums.length;i++){
            if(map.containsKey(target-nums[i])){
                res[0]=map.get(target-nums[i]);
                res[1]=i;
                break;
            }
            map.put(nums[i],i);
        }
        return res;
    }
}

11.左右双指针+字符串:整数反转

在这里插入图片描述

class Solution {
    public int reverse(int x) {
        String s=String.valueOf(x);
        char[] c=s.toCharArray();
        int n=s.length();
        int left=0,right=n-1;
        if(c[0]=='-'){
            left=1;
        }
        while (left<=right){
            char temp=c[left];
            c[left]=c[right];
            c[right]=temp;
            left++;
            right--;
        }
        s=String.valueOf(c);
        if(Double.valueOf(s)>(Math.pow(2,31)-1) || Double.valueOf(s)<(-Math.pow(2,31))){
            return 0;
        }else{
            return Integer.valueOf(s);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值